首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么我必须在“原始”指针上调用delete?

为什么我必须在“原始”指针上调用delete?
EN

Stack Overflow用户
提问于 2012-01-10 23:53:49
回答 4查看 286关注 0票数 3

我想知道为什么在下面的代码中,第一次删除不会释放内存:

代码语言:javascript
复制
#include <list>
#include <stdio.h>

struct abc {
    long a;

    abc() {
        puts("const");
    }
    ~abc() {
        puts("desc");
    }
};

int main() {

    std::list<abc*> test;

    abc* pA = new abc;
    printf("pA: 0x%lX\n", (unsigned long int)pA);
    test.push_back(pA);

    abc* pB = test.back();

    printf("pB: 0x%lX\n", (unsigned long int)pB);
    delete pB; // just ~abc()

    test.pop_back();

    delete pA; // ~abc() and free (works)

    puts("before double-free");

    delete pA; // ~abc() and second free (crash)

    return 0;
}

输出为:

代码语言:javascript
复制
const
pA: 0x93D8008
pB: 0x93D8008
desc
desc
before double-free
desc
*** glibc detected *** ./test: double free or corruption (fasttop): 0x093d8008 ***
...

我也用free()试过了,但行为是一样的。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-01-10 23:58:20

代码语言:javascript
复制
delete pA; // ~abc() and free (works)

puts("before double-free");

delete pA; // ~abc() and second free (crash)

这些delete语句是,而不是在编写delete pB时需要的。您有一个误解,即delete pB只调用析构函数。不,它调用析构函数并释放内存。

另外,由于您已经编写了delete pB,接下来的两个delete表达式将调用undefined behavior,这意味着任何事情都可能发生:程序可能崩溃,也可能不崩溃!

请看以下主题:

票数 4
EN

Stack Overflow用户

发布于 2012-01-11 00:04:21

您的第一个delete会将指针呈现为无效状态。所以现在使用指针会导致未定义行为。

代码语言:javascript
复制
int* p = new int;
delete p;
delete p; //undefined behaviour

根据标准,这是可以保证的(正如在第一条评论中指出的):

代码语言:javascript
复制
int* p = new int;
delete p;
p = 0;
delete p; //fine
票数 2
EN

Stack Overflow用户

发布于 2012-01-10 23:58:39

首先,你不能free分配给new的内存,你必须使用delete

其次,仅仅因为glibc没有立即检测到双重释放,你怎么知道 delete pB;没有释放它呢?这就是delete所做的,并且从您自己的日志记录中,您每次都会将相同的地址传递给delete

第三:你到底想要实现什么?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8806189

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档