C++ 中指针取消引用的随机行为
Posted
技术标签:
【中文标题】C++ 中指针取消引用的随机行为【英文标题】:Random behavior with Pointer de-referencing in C++ 【发布时间】:2014-11-13 23:15:55 【问题描述】:我有以下代码:
#include <iostream>
using namespace std;
int main ()
int myvar = 5;
int * p;
cout << "Hello2" << endl;
*p = myvar;
cout << "Hello" << endl;
cout << p << endl;
//cout << &myvar << endl;
我知道我没有通过初始化指针来做正确的事情。我只是在玩指针并注意到了这一点。问题是当我注释掉最后一行时,程序正常执行。但是,一旦我取消注释该行,就会出现分段错误。我不知道为什么 myvar 的打印地址会导致这种情况? myvar 是否因为指针取消引用而被修改过?我正在使用 C++11。
【问题讨论】:
未定义的行为是未定义的。 指针仅在指向某物时才起作用。 MSVC 2012 不会构建这个,不管有没有最后一行。 【参考方案1】:int* p;
*p = myvar;
您正在创建一个未初始化的指针,然后取消引用该指针。这具有未定义的行为,因为p
必须指向某些东西才能正确地引用它。因此,您的程序的行为无法推理。
【讨论】:
我意识到我没有通过不初始化指针来做正确的事情。关键是我已经运行了很多次,而 g++ 仅在我放入最后一行时给出分段错误,而不是在我将其注释掉时。我觉得这很令人惊讶,因为我没想到 myvar 变量会发生任何变化。我猜它应该总是打印 myvar 的地址。 @YogeshRane,“因此,您的程序的行为无法推理。”确实,未定义的行为甚至可以包括time travel。 @YogeshRane 我的猜测是编译器正在完全消除指针代码,因为它没有明显的效果。由于您正在打印&myvar
,因此编译器将不得不编译给出分段错误的部分。尝试在关闭优化的情况下运行以查看潜在差异。但同样,这可能只是未定义行为的影响,因此我们无法确定。
@0x499602D2 在 coliru 的 gcc 上,这个 UB 程序的效果重现性很好。据我所知,*p = myvar
并没有被消除,但是与 rbp 的偏移量有所不同,尽管我无法确定是什么,因为我看不到分配。【参考方案2】:
尝试访问没有读取权限的虚拟内存地址时发生分段错误。
在您的情况下,局部变量 p
保存堆栈中未初始化的垃圾。
您正在取消引用一个可能不可读的内存地址(例如,没有读取权限,因此在尝试访问它时会出现分段错误)。
【讨论】:
【参考方案3】:我不完全确定您的 sn-p 的用途,但以下代码会起作用,也许会有所帮助:
int myvar = 5;
int *p = nullptr;
p = &myvar;
cout << myvar << endl;
cout << &myvar << endl;
cout << p << endl;
cout << *p << endl;
(注意:我使用了两行来设置“p”,因为这就是你在 sn-p 中所做的。你可以很容易地使用:int *p = &myvar;)
无论如何,这里存在范围问题,因为 p 只有在 myvar 在范围内时才有效;但是,这确实说明了指针的基础知识。 myvar 和 *p 将返回相同的值(被指向的值),而 &myvar 和 p 将返回相同的值(值在内存中的位置)。
【讨论】:
以上是关于C++ 中指针取消引用的随机行为的主要内容,如果未能解决你的问题,请参考以下文章