我只是从C转移到C ++,目前正在通过异常切入我的路径。
我很难弄清楚为什么我在这个简单程序中出现内存泄漏:
#include <iostream> /* I/O */
#include <exception> /* exception */
#include <cstdlib> /* stdlib */
using namespace std;
void Bar()
{
throw exception();
}
void Foo()
{
int *ip = new int;
try
{
Bar();
}
catch(exception &e)
{
cerr << "Foo: Exception caught: " << e.what() << endl;
delete ip;
exit(1);
}
delete ip;
}
int main()
{
Foo();
return 0;
}
我觉得我在这里错过了一些至关重要的事情,但不能指出。有想法吗?
Valgrind的输出:
==21857== Memcheck, a memory error detector
==21857== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==21857== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==21857== Command: ./a.out
==21857==
Foo: Exception caught: std::exception
==21857==
==21857== HEAP SUMMARY:
==21857== in use at exit: 136 bytes in 1 blocks
==21857== total heap usage: 3 allocs, 2 frees, 72,844 bytes allocated
==21857==
==21857== 136 bytes in 1 blocks are possibly lost in loss record 1 of 1
==21857== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21857== by 0x4ECD8FF: __cxa_allocate_exception (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==21857== by 0x108CCC: Bar() (ex33.cpp:9)
==21857== by 0x108D0C: Foo() (ex33.cpp:18)
==21857== by 0x108DBD: main (ex33.cpp:31)
==21857==
==21857== LEAK SUMMARY:
==21857== definitely lost: 0 bytes in 0 blocks
==21857== indirectly lost: 0 bytes in 0 blocks
==21857== possibly lost: 136 bytes in 1 blocks
==21857== still reachable: 0 bytes in 0 blocks
==21857== suppressed: 0 bytes in 0 blocks
==21857==
==21857== For counts of detected and suppressed errors, rerun with: -v
==21857== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
答案 0 :(得分:7)
您不应真正在C ++中调用exit。本地对象的析构函数将不会被调用。并且原因堆栈不会被取消,看起来像异常的析构函数也不会被调用。
根据标准:
18.1.2引发异常时,控制权将转移到最近的匹配类型为(18.3)的处理程序; “最近”是指 复合语句或ctor初始化程序之后的处理程序 try关键字是最近由控制线程输入的, 尚未退出
18.1.3引发异常复制(初始化)(11.6,15.8)一个临时对象,称为异常对象。表示临时值的左值 用于初始化在匹配处理程序中声明的变量 (18.3)。如果异常对象的类型不完整 类型或指向cv以外的不完整类型的指针会使程序无效 格式不正确。
堆栈未解开:具有自动存储持续时间的变量的析构函数不会被调用。来自here
的引用答案 1 :(得分:0)
事实证明,将exit(1)
中的Foo()
替换为return;
可解决内存泄漏。
因此,我的后续问题是,为什么不能从exit()
呼叫Foo()
?