编辑:这个问题并不是一个讨论未定义行为的(de)优点的论坛,但这就是它的变化.在任何情况下,这个关于假设的C编译器没有未定义行为的线程可能对那些认为这是一个重要主题的人更感兴趣.
当然,"未定义行为"的经典伪装例子是"鼻子恶魔" - 物理上是不可能的,无论C和C++标准允许什么.
因为C和C++社区倾向于强调未定义行为的不可预测性以及允许编译器在遇到未定义行为时使程序完全做任何事情的想法,所以我假设标准没有任何限制关于行为,以及未定义的行为.
[C++14: defns.undefined]:[..]允许的未定义行为包括完全忽略不可预测的结果,在转换或程序执行期间以环境特征(有或没有发出诊断消息)的文档方式执行,终止转换或执行(发布诊断信息).[..]
这实际上指定了一小组可能的选项:
我假设在大多数情况下,编译器选择忽略未定义的行为; 例如,当读取未初始化的内存时,可能是插入任何代码以确保一致行为的反优化.我认为陌生人类型的未定义行为(例如" 时间旅行 ")将属于第二类 - 但这需要记录这些行为并"环境特征"(所以我猜鼻腔恶魔只能由地狱计算机?).
我误解了这个定义吗?这些仅仅是可能构成未定义行为的例子,而不是一个全面的选项列表吗?"任何可能发生的事情"的说法仅仅意味着忽视这种情况的意外副作用吗?
编辑:两个小问题澄清:
根据C++标准,每个实现都必须记录"实现定义的行为":
1.3.11
[defns.impl.defined]实现定义的行为行为,对于格式良好的程序构造和正确的数据,这取决于实现和每个实现文档
读取无效指针值具有实现定义的行为(请参阅4.1左值到右值转换[conv.lval]):
如果glvalue引用的对象包含无效指针值(3.7.4.2,3.7.4.3),则行为是实现定义的.
(引自n4527草案,但是"通过无效指针值间接并将无效指针值传递给释放函数的行为具有未定义的行为.无效指针值的任何其他使用都具有实现定义的行为."已经在3.7中. 4.2 [basic.stc.dynamic.deallocation]自至少草案n3485以来的释放功能
但是,许多流行的实现并未定义此行为,许多专家将此描述为"未定义的行为".
遗漏明确文件的一个可能原因是,据我所知,"附录后的标准草案"中出现的"实施定义行为指数"中缺少对"无效指针值"的评估.
这是标准中的缺陷吗?自C++ 14以来,是否有任何公开的缺陷报告或委员会行动?
我想知道如果我尝试对delete已经删除的指针执行操作,或者可能尚未分配,会有什么问题?我读过两件事:第一,delete操作员会做一些检查,我们不需要检查指针是否为空; 然后,我读到它可能导致未知的行为..
我问它,因为我使用了一些包含Qt对象属性的个人对象; 我认为Qt会删除关闭窗口时关联的所有小部件,但我不确定并且仍然如此:如果在窗口关闭之前软崩溃,我们必须手动删除所有对象.
那么,最好的解决方案是什么?那样的东西?
if( my_object )
delete my_object;
Run Code Online (Sandbox Code Playgroud)
它能避免危险的行为吗?
根据此,获取无效指针的值是C++中实现定义的行为.现在考虑以下C程序:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int* p=(int*)malloc(sizeof(int));
*p=3;
printf("%d\n",*p);
printf("%p\n",(void*)p);
free(p);
printf("%p\n",(void*)p); // Is this undefined or implementation defined in behaviour C?
}
Run Code Online (Sandbox Code Playgroud)
但是C中的行为也一样吗?上述C程序的行为是否未定义或实现定义?C99/C11标准对此有何看法?请告诉我C99和C11的行为是否不同.
(我引用的是ISO/IEC 9899:201x)
在这里我们看到,整数常量表达式具有整数类型:
6.6常量表达式
6. 整数常量表达式应具有整数类型,并且只能具有整数常量的操作数,枚举常量,字符常量,结果为整数常量的sizeof表达式,_Alignof表达式以及作为强制转换的直接操作数的浮点常量.整数常量表达式中的转换运算符只能将算术类型转换为整数类型,除非作为sizeof或_Alignof运算符的操作数的一部分.
这适用于任何整数类型:
6.2.6.2整数类型
5.未指定任何填充位的值.符号位为零的有符号整数类型的有效(非陷阱)对象表示是相应无符号类型的有效对象表示,并且应表示相同的值.对于任何整数类型,所有位为零的对象表示应该是该类型中零值的表示.
然后我们看到使用值为0的整数常量表达式定义空指针常量.
6.3.2.3指针
3. 值为0的整型常量表达式或类型为void*的表达式称为空指针常量.如果将空指针常量转换为指针类型,则保证将结果指针(称为空指针)与指向任何对象或函数的指针进行比较.
因此,空指针常量必须将其所有位设置为零.
但是在线和StackOverflow上有很多答案说这不是真的.
给出引用的部分,我很难相信他们.
(请使用最新标准的参考答案)
删除ptr后,是否cout << ptr打印 的地址int(6)?
如果是的话,为什么会出现乱码呢?我记得是delete只释放指定空间的数据吧?
还有我想问delete这里释放空间数据的时候,是只释放6还是连int类型都释放?
int* ptr = new int(6);
cout << "Address of the space pointed to by ptr: " << ptr << endl;
cout <<"the value of the space pointed to by ptr: "<< *ptr << endl;
delete ptr;
cout << ptr << endl;
Run Code Online (Sandbox Code Playgroud) 我刚学习了C++指针和删除指针.我自己尝试了这个代码
# include<iostream>
using namespace std;
int main(){
int num = 10;
int *p = new int;
p = #
cout << *p << endl;
delete p;
cout << num << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
删除指针后p,我无法打印值num.但如果我p在程序的最后删除,cout << num << endl;会给我10.任何人都知道我在哪里运行?
在代码块(C++)
#include<bits/stdc++.h>
using namespace std;
int main(){
int *p;
cout<<*p;
}
Run Code Online (Sandbox Code Playgroud)
产生垃圾价值,而
#include<bits/stdc++.h>
using namespace std;
int main(){
int *p=NULL;
cout<<*p;
}
Run Code Online (Sandbox Code Playgroud)
导致运行时错误.我预计两者的运行时错误(ideone会为两者产生运行时错误),因为两者都是错误的指针.怎么能解释这个呢?