根据valgrind下面的代码并没有包含内存泄漏:
#include <memory>
#include <stdexcept>
namespace {
class Foo {
public:
Foo();
};
Foo::Foo() { throw std::runtime_error("This is an error"); }
} // anonymous namespace
int main(int argc, char* argv[]) {
try {
new Foo();
} catch (const std::exception& aError) {
return -1;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
确实.结果valgrind --leak-check=full是:
==25913== Memcheck, a memory error detector
==25913== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==25913== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==25913== Command: ./test
==25913==
==25913==
==25913== HEAP SUMMARY:
==25913== in use at exit: 0 bytes in 0 blocks
==25913== total heap usage: 4 allocs, 4 frees, 72,890 bytes allocated
==25913==
==25913== All heap blocks were freed -- no leaks are possible
==25913==
==25913== For counts of detected and suppressed errors, rerun with: -v
==25913== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Run Code Online (Sandbox Code Playgroud)
该程序编译为g++ (GCC) 7.3.0.
注意:即使有,也没有泄漏clang 5.0.1.
注意:我检查了反汇编代码,并且有delete电话.
我的问题:为什么这段代码不会产生内存泄漏?它是否真的在标准中指定(可以链接吗?)或只是自主编译器增强?
我期待的是:
...
call operator new(unsigned long)
mov rbx, rax
mov rdi, rbx
call (anonymous namespace)::Foo::Foo()
Run Code Online (Sandbox Code Playgroud)
动态分配发生在调用生成泄漏的构造函数之后.
如果构造函数抛出异常,则内存不会泄漏,因为如果存在适当的释放函数,则分配器必须在传递异常之前释放内存.
根据2017年3月的工作草案:
8.3.4新[expr.new]
20如果new-expression创建一个对象或类类型的对象数组,则对分配函数,释放函数(15.5)和构造函数(15.1)进行访问和歧义控制.如果 new-expression创建了类类型的对象数组,则可能会调用析构函数(15.4).
21如果上面描述的对象初始化的任何部分80通过抛出异常终止并且可以找到合适的解除分配函数,则调用释放函数以释放构造对象的存储器,之后异常继续传播.新表达的背景. 如果找不到明确的匹配解除分配函数,则传播异常不会导致释放对象的内存.[注意:当被调用的分配函数不分配内存时,这是合适的; 否则,很可能导致内存泄漏. - 结束说明]
80)这可能包括评估新初始化程序和/或调用构造函数
另外,根据C++ wiki中的Exceptions FAQ:
"但是从调用的构造函数中抛出异常
new导致内存泄漏!"废话!这是一个由一个编译器中的错误引起的老太太的故事 - 这个错误在十年前就被立即修复了.
| 归档时间: |
|
| 查看次数: |
74 次 |
| 最近记录: |