下面的代码编译正常但不执行
#include <iostream>
using namespace std;
int main()
{
int *a;
int b = 5;
a = &b;
cout << *a << endl;
delete a;
return 0;
}
编辑:
int main()
{
int *a = 0;
delete a;
return 0;
}
这工作正常。为什么呢?
下面的代码编译正常但不执行
#include <iostream>
using namespace std;
int main()
{
int *a;
int b = 5;
a = &b;
cout << *a << endl;
delete a;
return 0;
}
编辑:
int main()
{
int *a = 0;
delete a;
return 0;
}
这工作正常。为什么呢?
编辑后,您只有一种未定义行为的情况:
delete
您没有获得的记忆new
。
delete
在 NULL 指针上保证不会造成任何伤害。但是delete
在你之前没有分配或删除的内存上是未定义的。我知道的实现以某种访问冲突退出您的程序。
“未定义的行为”意味着您所做的事情没有保证的后置条件。
人们经常会说“编译器”选择了发生的事情。实际上,编译器将编译它,堆管理器在运行时决定它如何处理您调用无效删除调用的情况。
尽管这里的情况在编译器级别上看起来微不足道,但在许多情况下,它只是超出了编译器的范围。
它会导致未定义的行为
这两个因素最有可能导致“访问冲突”崩溃。
但是,由于行为未定义,应用程序可以工作。
您有三种未定义行为的情况:第一种是使用未初始化的指针取消引用和分配a
,第二种是打印时取消引用a
,最后是删除时a
。
对尚未分配new或空指针的指针调用delete是未定义的行为,草案 C++ 标准部分删除第2段说(强调我的):5.3.5
[...]在第一种选择(删除对象)中,delete 的操作数的值可以是空指针值,指向由先前的 new 表达式创建的非数组对象的指针,或指向子对象的指针(1.8) 表示此类对象的基类(第 10 条)。如果不是,则行为未定义。
与所有未定义的行为一样,一切皆有可能,该程序甚至看起来工作正常,但结果不可靠。
您正在尝试删除堆栈内存。如果您试图删除它,堆栈内存将具有传染性,将发生未定义的行为。
因为堆内存分配不会传染。
您正在尝试写入不是您分配的内存位置。
*a = 5;
然后尝试删除不是你分配的内存
删除一个;
它具有未定义的行为。