处理异常时发生内存泄漏

时间:2020-04-27 14:39:54

标签: c++ exception memory-leaks

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

2 个答案:

答案 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()