C++;取消引用cout的指针时出现SEGFULT 我对C++很陌生,只是想了解一下它。一般来说,这似乎不太糟糕,但我偶然发现了这种奇怪/病态的错误行为: int main () { int* b; *b = 27; int c = *b; cout << "c points to " << c << endl; //OK printf( "b points to %d\n", *b); //OK // cout << "b points to " << (*b) << endl; - Not OK: segfaults! return 0; }
另一方面,如果取消注释倒数第二行,则会得到一个程序在运行时崩溃(seg fault)。为什么?这是一个有效的指针 指针只要有值就有效。但记忆可能不是。这是你的操作系统告诉你,你正在触摸的内存不是你的 坦率地说,我很惊讶它没有比那更早崩溃C++;取消引用cout的指针时出现SEGFULT 我对C++很陌生,只是想了解一下它。一般来说,这似乎不太糟糕,但我偶然发现了这种奇怪/病态的错误行为: int main () { int* b; *b = 27; int c = *b; cout << "c points to " << c << endl; //OK printf( "b points to %d\n", *b); //OK // cout << "b points to " << (*b) << endl; - Not OK: segfaults! return 0; },c++,pointers,segmentation-fault,cout,C++,Pointers,Segmentation Fault,Cout,另一方面,如果取消注释倒数第二行,则会得到一个程序在运行时崩溃(seg fault)。为什么?这是一个有效的指针 指针只要有值就有效。但记忆可能不是。这是你的操作系统告诉你,你正在触摸的内存不是你的 坦率地说,我很惊讶它没有比那更早崩溃 原因如下: int* b; // b is uninitialized. *b = 27; b指向哪里?它可能在某个有效的地方,或者完全禁止的地方。你通常可以赌后者 这里有一个更好的方法来做你想做的事 int b1 = 27; int *b = &b
原因如下:
int* b; // b is uninitialized.
*b = 27;
b
指向哪里?它可能在某个有效的地方,或者完全禁止的地方。你通常可以赌后者
这里有一个更好的方法来做你想做的事
int b1 = 27;
int *b = &b1;
现在
b
指向堆栈上存储b1
s值的位置。int*b
指向未知内存地址,因为它未初始化。如果您将它初始化为编译器存在的任何空指针值(0
直到C++11,nullptr
在C++11及更高版本中),您肯定会更早地得到一个segfault。问题在于您为指针分配了空间,而不是它指向的数据。如果您改为这样做:
int c = 27;
int* b = &c;
cout << "c points to " << c << endl;
printf ("b points to %d\n", *b);
cout << "b points to " << (*b) << endl;
这是因为
f
是一个指针,需要为它分配一些内存。更新3
对于为什么使用未初始化的指针是未定义的行为,我的答案给出了一个更好的答案。“迭代器要求”一节中的基本逻辑,特别是第5段和第10段中的“迭代器要求”一节中的基本逻辑,分别表示(重点):
[…][示例:在声明未初始化指针x(与int*x;)之后,必须始终假定x具有指针的奇异值-结束示例][…]可取消引用的值始终是非奇异值。
更新2
这本来是一个C问题的答案,情况几乎相同,但我原来回答的问题与这个问题合并了。我正在更新我的答案,包括一个新的问题和C++草稿标准的答案。
b
尚未初始化,因此其值是不确定的,但您在b
上使用了间接寻址,这是不确定的
一种可能的简单修复方法是将b
分配给现有变量的地址,例如:
int a ;
int* b = &a;
另一种选择是通过新的方式使用动态分配
完整性的缘故,我们可以看到这是未定义的行为,通过C++标准部分草案>代码> 5.3.1 < /代码>一元运算符第1段(强调矿):
一元*运算符执行间接寻址:应用它的表达式应是指向对象类型的指针,或指向函数类型的指针,结果是引用表达式所指向的对象或函数的左值。[…] 如果我们再转到第3.10节,左值和右值第1段说(我的重点): 左值(历史上称为左值,因为左值可能出现在赋值表达式的左侧)指定函数或对象。[……] 但是b
没有指向有效的对象
原始答案
您没有将任何内存分配给f
或b
,但在这两个内存上都使用了间接寻址
更新
值得注意的是,提高警告级别本应表明这是一个问题,例如,使用gcc-Wall
对此代码给出以下警告:
warning: 'f' is used uninitialized in this function [-Wuninitialized]
最简单的修复方法是指定f
指向有效对象,如下所示:
char a ;
char *f = &a ;
另一个选择是使用动态分配,如果你没有一个方便的参考资料,那么这是一个不错的开始
为完整起见,如果我们查看附录J.2
未定义的行为,第1段说:
在以下情况下,该行为未定义:
并包括以下项目符号:
具有自动存储持续时间的对象的值将在其运行时使用
不确定(6.2.4、6.7.8、6.8)
f
和b
的值都是自动变量,由于未初始化,因此不确定
阅读参考章节时,不清楚哪一条语句使其未定义,但第6.5.2.5节
复合文字第17段是规范性文本的一部分,该段有一个示例,其中使用了相同的语言,如下所示:
[…]下一次p附近将有一个不确定的值,这将导致未定义的行为
在第16段中。一般规则:在使用变量之前初始化它
char*f代码>是一个变量*f
是此变量的用法。像任何变量一样,f
必须在使用前进行初始化。你只是告诉他seg故障是什么,而不是真正解决问题。@Dhaivat Pandya-他只是回答了OP的答案。解决办法很清楚。那么,我需要使用new使int*保持有效地址的解决方案是什么呢?等等,为什么最后一行不起作用?(为自己是个笨蛋而抱歉)也许有一个很好的理由,但这并不重要。这是一个未定义的行为。学究式的说,最后一句话是不相关的,因为指针根本没有被赋值。他们的价值观是不确定的。@OliCharlesworth他们的价值观是不确定的,现在让我来考虑一下,有机会的话再修改一下。我会认为无效,但也许你是正确的。是的,这是挑剔。这里的问题是“分配”这个词。@ShafikYaghmour,你的意思是他们没有被分配变量吗?而是绝对
warning: 'f' is used uninitialized in this function [-Wuninitialized]
char a ;
char *f = &a ;