【问题标题】:Accessing invalid pointer and taking its address访问无效指针并获取其地址
【发布时间】:2016-12-01 05:56:10
【问题描述】:

考虑这样的代码:

std::vector<int> vec { 1, 2, 3 };
auto addr = &*vec.end();

或简化:

int* ptr = 0;
auto addr = &*ptr;

很明显auto val = *ptr; 会出现段错误。因此&amp;*ptr 没有以相同的方式访问内存。为什么会这样?标准中有具体的条目吗?

【问题讨论】:

  • "很明显auto val = *ptr; 会出现段错误。" - 它是?你会希望它会出现段错误,因为这样会更容易发现你的代码有缺陷,但是调用 undefined behavior (这发生在你应用对容器结束迭代器的取消引用运算符)不能保证它会出现段错误,具有“工作”的所有外观或其他任何东西。行为是未定义;除了行为的定义,你不能排除任何事情

标签: c++ memory stl


【解决方案1】:

取消引用 std::vector::end() 的返回值是导致未定义行为的原因。如果你这样做了,试图理解会发生什么是没有意义的。

来自http://en.cppreference.com/w/cpp/container/vector/end

此元素充当占位符;尝试访问它会导致未定义的行为。

回复。第二部分,我在 C++11 标准中唯一能找到的是:

5.3.1 一元运算符

1 一元* 运算符执行间接:应用它的表达式应该是指向对象类型的指针,或指向函数类型的指针,结果是一个左值引用指向表达式指向的对象或函数。如果表达式的类型是“指向T 的指针”,则结果的类型是“T”。 [ 注意: 指向不完整类型的指针(cv void 除外)可以被取消引用。这样获得的左值可以以有限的方式使用(例如,初始化引用);此左值不得转换为 prvalue,见 4.1。 — 尾注 ]

取消引用 NULL 指针的结果似乎未指定。

【讨论】:

  • 这不是问题。看第二个例子,解释为什么没有seg fault
  • @PRP,第一个问题就是这样。
  • 预期的问题是,在执行 auto addr = &amp;(*ptr); 时,是否首先取消引用指针然后计算地址。如果是,那么为什么指针的取消引用没有给出段错误。
  • @PRP 因为取消引用坏指针的结果是未定义的。它可能会出现段错误。它可以通过电子邮件将 ascii 艺术蒙娜丽莎发送给 Cobra Commander。你不知道它会做什么。
  • 关于 SO 有两个相关问题: * stackoverflow.com/questions/2728299/… * stackoverflow.com/questions/2728299/… 请注意其中一个是 Stepanov 的代码,另一个是 C 标准引用。
【解决方案2】:

在这两种情况下,您最终都会计算地址而不是访问内存,这就是您的代码恰好可以工作的原因。但是根据 c++ 标准,这两种情况都是未定义的行为。第一个例子实际上可能会在标准库的 Debug 版本中触发断言失败。

【讨论】:

  • 问题来了:如果是这样的话,这种区别(访问内存与“计算地址”)在标准中是在哪里进行的?
  • 标准中没有区别,都是未定义的行为。但实际上只有当程序需要读取内存内容时才会出现段错误。
猜你喜欢
  • 2015-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多