简体   繁体   English

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

[英]Why I have to call delete on the “original” pointer?

I would like to know why in the following code the first delete won't free the memory: 我想知道为什么在下面的代码中第一次删除不会释放内存:

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

Output is: 输出是:

const
pA: 0x93D8008
pB: 0x93D8008
desc
desc
before double-free
desc
*** glibc detected *** ./test: double free or corruption (fasttop): 0x093d8008 ***
...

I tried it with free() also but same behavior. 我尝试了free()也行为相同。

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

puts("before double-free");

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

These delete statements are not needed once you write delete pB . 一旦编写delete pB 不需要这些delete语句。 You've a misconception that delete pB only calls the destructor. 你错误地认为delete pB只调用析构函数。 No, it calls the destructor and also deallocates the memory. 不,它调用析构函数并释放内存。

Also, since you've already written delete pB , the next two further delete expressions invoke undefined behavior , which means anything can happen : the program may or may not crash! 此外,由于您已经编写了delete pB ,接下来的两个delete表达式会调用未定义的行为 ,这意味着任何事情都可能发生:程序可能会可能不会崩溃!

Have a look at these topics: 看看这些主题:

Your first delete renders the pointer to invalid state. 您的第一次删除会将指针呈现为无效状态。 So use of that pointer now leads to undefined behaviour. 因此,使用该指针现在会导致未定义的行为。

int* p = new int;
delete p;
delete p; //undefined behaviour

This is guaranteed to be fine by the standard (as pointed out in the first comment): 按标准保证这是正常的(如第一条评论中所指出的):

int* p = new int;
delete p;
p = 0;
delete p; //fine

First, you can't free memory allocated with new , you have to use delete . 首先,你不能free分配new内存,你必须使用delete

Secondly, just because glibc doesn't detect the double free immediately, how do you know delete pB; 其次,只是因为glibc没有立即检测到双重释放,你怎么知道 delete pB; isn't freeing it? 是不是正在释放它? That's what delete does, and from your own logging you're passing the same address to delete each time. 这就是delete操作,并且从您自己的日志记录中,您每次都要传递相同的地址进行delete

Thirdly: what are you actually trying to accomplish? 第三:你究竟想要完成什么?

It's just an indiosyncracy of your compiler/platform that you had to call delete twice on pA before glibc complained ... for instance, on my current platform, which is OSX 10.6.8 with gcc version i686-apple-darwin10-gcc-4.2.1, I get the following output: 这只是你的编译器/平台的indiosyncracy你不得不打电话给delete两次pAglibc抱怨......比如,我现在的平台,这是OSX 10.6.8上gcc版本的i686-苹果darwin10-GCC-4.2 .1,我得到以下输出:

const
pA: 0x100100080
pB: 0x100100080
desc
desc
test(14410) malloc: *** error for object 0x100100080: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap

So you can see the first call to delete on pA , which by the standard results in undefined behavior since you didn't set the pointer to NULL or 0 , did get caught as an attempt to deallocate already deallocated memory by the C++ run-time on my platform. 所以你可以在pA上看到第一次调用delete ,由于你没有将指针设置为NULL0 ,标准会导致未定义的行为,因为尝试通过C ++运行时释放已经释放的内存在我的平台上。

Since the results of the double-delete are "undefined behavior", it's really up to the implementation and platform on what happens. 由于双删除的结果是“未定义的行为”,因此实际上取决于所实现的实现和平台。

You may be able to detect allocation/deallocation memory errors quicker if you use the link against the glibc memory consistency checker by compiling with the -lmcheck flag. 如果通过使用-lmcheck标志进行编译来使用针对glibc内存一致性检查程序的链接,则可以更快地检测分配/释放内存错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当我在空指针上调用“delete”时,为什么会调用“operator delete”? - Why is “operator delete” invoked when I call “delete” on a null pointer? 为什么我删除指向基类的指针我有内存泄漏? - Why if I delete the pointer to the base class I have a memory leak? 为什么将原始指针转换为unique_ptr不会删除原始指针? - Why does casting a raw pointer to a unique_ptr not delete the original? 我可以在这个析构函数中调用delete吗? - Have I to call delete in this destructors? 当两个指针都位于同一内存时,为什么必须两次调用“删除”? - Why do I have to call “delete” twice when I have each two pointers at same memory? 在这里的析构函数中删除后,为什么会创建潜在的流浪指针? - Why do I have created a potential stray pointer when having delete in the destructor here? 为什么在第二次调用“删除此”指针之后运行对象的方法 - Why can I run object's method after “delete this” pointer at second time call 我是否需要将delete调用给分配给另一个指针的指针? - Do I need to call delete to a pointer assigned to another pointer? 为什么我在此删除中有异常? - Why I have an exception in this delete? 如果我超载它,如何调用原始的“operator new”? - How do I call the original “operator new” if I have overloaded it?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM