处理异常时内存泄漏



我只是从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)

您不应该在C++中调用exit。不会调用本地对象析构函数。并且导致堆栈不会被打开,看起来异常的析构函数也不会被调用。

来自标准:

18.1.2当抛出异常时,控制权将转移到具有匹配类型的最近处理程序(18.3(;"最近的"是指复合语句或ctor初始值设定项跟随的处理程序try关键字最近由控件和尚未退出

18.1.3抛出异常副本会初始化(11.6,15.8(一个临时对象,称为异常对象。表示临时用于初始化匹配处理程序中声明的变量(18.3(.如果异常对象的类型是不完整的类型或指向cv以外的不完整类型的指针使程序无效不正规。

堆栈未展开:不调用具有自动存储持续时间的变量的析构函数。从这里报价

事实证明,将exit(1)Foo()替换为return;修复了内存泄漏。

那么,我的后续问题是,为什么我不能从Foo()呼叫exit()

最新更新