c++析构函数和内存分配,以及未定义的行为
C++ destructor and memory allocation, and undefined beahviour
首先:我知道如果对象的析构函数抛出了应用程序的行为,就不能指望…这个问题是关于内存的。
那么,现在清楚了:
查看应用程序:
#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报告没有内存泄漏…这让我很困惑……所以我认为发生的是:
- call
delete t;
- 应用程序释放
t
的内存 -
t
的析构函数被调用。
你能解释一下这里发生了什么吗?
编辑:有一个更明确的问题:
是否在释放的内存上调用析构函数,或者当std::cout获得空对象时,析构函数中没有未定义的行为?
未定义行为未定义。
如果我不得不猜测,在这种情况下,流检测到空指针并进入错误状态,因此您根本看不到任何更多的输出。其余的删除过程显然如预期的那样继续。
其他形式的未定义行为,例如实际解引用空指针,可能会给出不同的结果。同样,当您打破其他流实现的需求时,它们的行为可能会有所不同。
Valgrind是正确的,没有内存泄漏。
您在堆中分配了变量t
,但没有分配类t的内部工作方式。因此,由于您使用delete
承担了释放内存的责任,因此析构函数没有什么可释放的。
您可以在Class T
内部分配变量,而不是在析构函数中释放它以查看内存泄漏。
相关文章:
- 添加自定义析构函数时,Move 构造函数在派生类中消失
- 在从仅移动类型派生的类中定义析构函数在使用 std::vector emplace_back或push_back创建时会
- 为什么在定义析构函数时隐式删除移动构造函数
- 仅在删除包含对象的向量时调用自定义»析构函数«
- 这个递归类需要一个自定义析构函数?
- C++ - 定义自定义析构函数时程序崩溃
- 对象超出范围后未调用析构函数
- 定义析构函数可以防止成员函数内联
- 在scoped_ptr发生异常的情况下未调用析构函数
- 使用自定义析构函数时出现"Undefined reference"错误
- 未调用析构函数
- C++ 在迭代器类中定义析构函数
- `不可复制`与自定义析构函数
- 堆栈上的对象被覆盖时未调用析构函数
- 是否可以使用 std::shared_ptr 创建共享对象池,并在没有自定义析构函数的情况下创建weak_ptr
- 我们什么时候必须在派生类 c++ 中定义析构函数
- 未调用析构函数
- C++unique_ptr未调用析构函数
- 未调用析构函数,程序异常退出时出现问题
- 抛出异常时未调用析构函数