【问题标题】:Is this a double free in C++这是 C++ 中的双重免费吗
【发布时间】:2020-12-23 06:42:17
【问题描述】:

我以为下面的代码 sn-ps 会导致双重释放,程序会核心转储。但事实是我运行代码时没有错误?

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;
}

当我运行这个程序时,程序的输出如下所示:

如下修改代码sn-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;
}

程序输出是:

那么还有一个问题,为什么这个程序每次都会转储内核?

【问题讨论】:

  • 为什么没有错误显示有双重释放? - 因为不需要编译器为类似的事情提供诊断。首先不要使用拥有指针。

标签: c++ memory-management memory-leaks free


【解决方案1】:

是的,它是双重free(嗯,三重,真的)将其置于未定义的行为领域。

但这就是关于未定义行为的阴险事情,它不是必需崩溃或抱怨,它根本不是必需做任何事情(a)。它甚至可能工作。

我可以设想一个实现,将块的空闲状态存储在它的控制信息中,这样两次释放它就没有效果了。但是,这将是低效的,并且也不会涵盖它已被重新分配用于其他目的的情况(它会阻止双重释放,但当其他部分仍然认为它仍然拥有它时,它不会释放块的一段代码) .

因此,鉴于它不是必需工作,建议您很好避开它,因为它可能也下载@987654323 @ 并在擦除主驱动器时播放它。

顺便说一句,现代 C++ 具有能够管理其自己的生命周期的智能指针,如果您开始使用这些智能指针而不是原始指针,那么您会帮自己一个大忙。
而且,虽然the removal of raw pointer from C++ 是个玩笑,但也有人认为这不是一个坏主意 :-)


(a)C++20 标准在描述[defns.undefined] 中未定义的行为时有这样的说法(我的重点):

本文档规定**NO**要求的行为。

【讨论】:

    【解决方案2】:

    为什么没有报错说明有double free?为什么没有核心转储?

    delete p;
    cout << "The value that p points to: " << (*p) << endl;
    

    您引用已删除指针的时刻是程序进入未定义行为的时刻,因此无法保证会出现错误或崩溃。

    这并不完全一样,但内存和酒店房间之间的类比是适用的,这很好地解释了未定义行为的含义。强烈推荐阅读:

    Can a local variable's memory be accessed outside its scope?

    【讨论】:

    • 当程序进入未定义的行为时 – 程序不能“进入 ub”。如果程序中有 ub,则整个程序都有 ub,并且不再是有效的 C++ 程序。
    • 有没有办法修改代码sn-p,每次都让core dump出来?
    • @George 重新阅读我的评论。您的问题的答案:否。
    • @Swordfish 只是术语,输入 UB 还是有 UB,对我来说差别不大。
    • @George Undefined Behavior 的行为是未定义的,因此您无法修改程序以保证特定的结果。也就是说,在给定有关目标平台的足够信息的情况下,结果通常在实践中是可以预测的,但我想不出一种方法来保证这里的硬可见错误。最好的办法是完全避免错误with smarter pointer management。
    猜你喜欢
    • 1970-01-01
    • 2016-08-17
    • 2011-11-06
    • 1970-01-01
    • 2015-04-03
    • 2021-09-16
    • 1970-01-01
    • 2021-07-22
    • 1970-01-01
    相关资源
    最近更新 更多