即使使用智能指针,C++也会在异常情况下泄漏

efa*_*bor 9 c++ memory-leaks smart-pointers

我是智能指针世界的新手.我已经完成了我的阅读,并且所有人都表示即使程序在遇到异常后退出,智能指针也会避免泄漏内存.

我写了一个简单的程序试试这个,但Valgrind告诉我我的程序泄漏了内存(三个分配,只有一个免费).

这是源代码:

#include <iostream>
#include <memory>

using namespace std;

int main()
{
    auto_ptr<int> ptr_int(new int(5));

    throw std::bad_alloc();

    cout << *ptr_int;
}
Run Code Online (Sandbox Code Playgroud)

这个Valgrind的报告:

==27862== Memcheck, a memory error detector
==27862== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==27862== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==27862== Command: ./smart_pointers
==27862== Parent PID: 5388
==27862==
==27862==
==27862== HEAP SUMMARY:
==27862==     in use at exit: 104 bytes in 2 blocks
==27862==   total heap usage: 3 allocs, 1 frees, 120 bytes allocated
==27862==
==27862== 4 bytes in 1 blocks are still reachable in loss record 1 of 2
==27862==    at 0x4026351: operator new(unsigned int) (vg_replace_malloc.c:255)
==27862==    by 0x804878A: main (smart_pointers.cpp:8)
==27862==
==27862== 100 bytes in 1 blocks are possibly lost in loss record 2 of 2
==27862==    at 0x4025BD3: malloc (vg_replace_malloc.c:236)
==27862==    by 0x40E861A: __cxa_allocate_exception (in /usr/lib/libstdc++.so.6.0.14)
==27862==    by 0x80487AE: main (smart_pointers.cpp:10)
==27862==
==27862== LEAK SUMMARY:
==27862==    definitely lost: 0 bytes in 0 blocks
==27862==    indirectly lost: 0 bytes in 0 blocks
==27862==      possibly lost: 100 bytes in 1 blocks
==27862==    still reachable: 4 bytes in 1 blocks
==27862==         suppressed: 0 bytes in 0 blocks
==27862==
==27862== For counts of detected and suppressed errors, rerun with: -v
==27862== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 19 from 8)
Run Code Online (Sandbox Code Playgroud)

使用智能指针是否保证即使出现异常,分配的资源也会被销毁?

Mik*_*our 12

如果没有处理异常,那么它的实现定义是否在调用之前将堆栈展开std::terminate.

如果处理异常,则智能指针将按预期工作.

参考:

C++ 11 15.5.1该std::terminate()函数

1在某些情况下,必须放弃异常处理以获得不那么微妙的错误处理技术.这些情况是:

........

- 当异常处理机制找不到抛出异常的处理程序时,或

........

2在这种情况下std::terminate()被称为.在没有找到匹配处理程序的情况下,无论堆栈是否在std::terminate()被调用之前被展开,它都是实现定义的.


mod*_*ine 5

std::terminate()被调用(如对于未捕获的异常的情况下),正常清理没有(至少对于堆栈帧运行main()),因此内存你在栈帧泄漏分配,即使它理应管理通过智能指针.当你捕捉std::bad_allocmain(),和正常返回,智能指针会做它的职责.

  • 我不知道C++ 11,但最初,在C++中,是否在未处理的异常上调用析构函数是由实现决定的.至关重要:一些析构函数不仅仅是回收内存(例如,干净地关闭服务器连接,删除临时文件,......).因此,有人可能会说,即使在这种情况下调用析构函数也是有意义的.但是,考虑到将一个catch-all添加到`main`并且不解开堆栈可以帮助调试它是微不足道的,它没有强制要求.我不知道是否有任何实现可以解除未捕获异常的堆栈. (2认同)