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 我的猜测是编译器正在完全消除指针代码,因为它没有明显的效果。由于您正在打印&amp;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++ 中指针取消引用的随机行为的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中取消引用指针对象?

C++:取消引用指针

为啥 C++ 共享指针的行为不像迭代器的标准指针?

具有正确地址但具有另一个随机值的 C++ 指针?

不评估应用了 sizeof 的表达式是不是使得在 C++ 中取消引用 sizeof 内的空指针或无效指针是合法的?

C++ 指针取消引用赋值