问题描述
我认为以下代码片段将导致double free,并且该程序将进行核心转储。但是事实是我运行代码时没有错误吗?
Similar problem表明它引起了双重释放!
我的问题是,为什么没有错误表明有双重免费?为什么没有核心转储?
#include <iostream>
using namespace std;
int main()
{
int *p = new int(5);
cout << "The value that p points to: " << (*p) << endl;
cout << "The address that p points to: " << &(*p) << endl;
delete p;
cout << "The value that p points to: " << (*p) << endl;
cout << "The address that p points to: " << &(*p) << endl;
delete p;
cout << "The value that p points to: " << (*p) << endl;
cout << "The address that p points to: " << &(*p) << endl;
delete p;
}
在修改了如下代码段之后,发生了核心转储:
#include <iostream>
using namespace std;
int main()
{
int *p = new int(5);
for (;;)
{
cout << "The value that p points to: " << (*p) << endl;
cout << "The address that p points to: " << &(*p) << endl;
delete p;
}
return 0;
}
还有另一个问题,为什么这个程序每次都会核心转储?
解决方法
是的,它是双free
(真的,三重),将其置于未定义的行为范围内。
但这就是关于未定义行为的阴险 ,不是要求崩溃或抱怨,完全不需要 做任何事情(a)。它甚至可以起作用。
我可以设想一个实现,该实现将块的空闲状态存储在其控制信息中,这样两次释放就不会产生任何效果。但是,这将是低效的,并且也不会涵盖已将其重新分配用于其他目的的情况(这将防止双重释放,但是当另一些代码仍然认为它仍然具有该代码块时,则不会有一段代码释放该块)
因此,鉴于不需要工作,建议您 避免使用它,因为它可能也下载{{ 1}},然后在擦除主驱动器时播放它。
顺便说一句,现代C ++具有能够管理其 own 生命周期的智能指针,如果您开始使用那些指针而不是原始指针,那么您将大受青睐。
而且,尽管the removal of raw pointer from C++是个玩笑,但有些人认为这不是一个坏主意:-)
(a)maniacal_laughter.ogg
标准在描述C++20
中未定义的行为时(我强调):
,此文档强加了 ** NO ** 要求的行为。
为什么没有错误表明有双重免费?为什么没有核心转储?
delete p;
cout << "The value that p points to: " << (*p) << endl;
引用删除的指针的时刻是程序输入未定义的行为时,则不能保证会出现错误或崩溃。
这并不完全相同,但是内存和旅馆房间之间的类比是适用的,这很好地解释了未定义行为的含义。强烈建议阅读:
Can a local variable's memory be accessed outside its scope?