c++析构函数和内存分配,以及未定义的行为

C++ destructor and memory allocation, and undefined beahviour

本文关键字:未定义 析构函数 内存 分配 c++      更新时间:2023-10-16

首先:我知道如果对象的析构函数抛出了应用程序的行为,就不能指望…这个问题是关于内存的。

那么,现在清楚了:

查看应用程序:

#include <stdlib.h>
#include <iostream>
class T
{
    public:
        T() : ma(0) 
             {std::cout << "T::T ->default<-" << std::endl; }
        T(const char* a) : ma(a) 
             {std::cout << "T::T ->" << ma << "<-" << std::endl; }
        ~T() 
             {std::cout << "T::~T ->" << ma << "<-" << std::endl; }
    private:
        const char* ma;
};
int main()
{
    T* t = new T();
    delete t;
}

并查看它的valgrind输出:

$ valgrind ./a.out
==29554== Memcheck, a memory error detector
==29554== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==29554== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==29554== Command: ./a.out
==29554== 
T::T ->default<-
T::~T ->==29554== 
==29554== HEAP SUMMARY:
==29554==     in use at exit: 0 bytes in 0 blocks
==29554==   total heap usage: 1 allocs, 1 frees, 4 bytes allocated
==29554== 
==29554== All heap blocks were freed -- no leaks are possible
==29554== 
==29554== For counts of detected and suppressed errors, rerun with: -v
==29554== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

解释:T::~T ->==29554==告诉我析构函数遇到了一个危险的情况(std::cout接受了一个未定义的空值),所以应用程序的行为是不可控的…

因为它没有打印出"<-",而且它立即给了我valgrind提示,我希望它在那个特定的点退出。Valgrind不报告任何段错误或类似的东西…

但是,valgrind报告没有内存泄漏…这让我很困惑……所以我认为发生的是:

  1. call delete t;
  2. 应用程序释放t 的内存
  3. t的析构函数被调用。

你能解释一下这里发生了什么吗?

编辑:有一个更明确的问题:

是否在释放的内存上调用析构函数,或者当std::cout获得空对象时,析构函数中没有未定义的行为?

未定义行为未定义。

如果我不得不猜测,在这种情况下,流检测到空指针并进入错误状态,因此您根本看不到任何更多的输出。其余的删除过程显然如预期的那样继续。

其他形式的未定义行为,例如实际解引用空指针,可能会给出不同的结果。同样,当您打破其他流实现的需求时,它们的行为可能会有所不同。

Valgrind是正确的,没有内存泄漏。

您在堆中分配了变量t,但没有分配类t的内部工作方式。因此,由于您使用delete承担了释放内存的责任,因此析构函数没有什么可释放的。

您可以在Class T内部分配变量,而不是在析构函数中释放它以查看内存泄漏。