处理异常可能导致内存泄漏吗?(通过调用 exit() 的异常处理。)

Int*_*ity 2 c++ valgrind memory-leaks exception

我正在开发一个 C++ 应用程序(大学的 OpenSSL 作业),并且我通过 valgrind 运行它,就像人们所做的那样。当程序因无效输入而失败时,我注意到一些相当奇怪的输出:

==1739== HEAP SUMMARY:
==1739==     in use at exit: 588 bytes in 6 blocks
==1739==   total heap usage: 52 allocs, 46 frees, 99,206 bytes allocated
==1739== 
==1739== 44 bytes in 1 blocks are possibly lost in loss record 3 of 6
==1739==    at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1739==    by 0x4C20378: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1739==    by 0x4C03187: std::logic_error::logic_error(char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1739==    by 0x4C0325C: std::invalid_argument::invalid_argument(char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1739==    by 0x10FB6D: lab2::cryptoEngine::CBCCryptoEngine::encrypt() (CBCCryptoEngine.cpp:39)
==1739==    by 0x10E355: main (main.cpp:135)
==1739== 
==1739== 144 bytes in 1 blocks are possibly lost in loss record 4 of 6
==1739==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1739==    by 0x4BDB1F3: __cxa_allocate_exception (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1739==    by 0x10FB5B: lab2::cryptoEngine::CBCCryptoEngine::encrypt() (CBCCryptoEngine.cpp:39)
==1739==    by 0x10E355: main (main.cpp:135)
==1739== 
==1739== LEAK SUMMARY:
==1739==    definitely lost: 0 bytes in 0 blocks
==1739==    indirectly lost: 0 bytes in 0 blocks
==1739==      possibly lost: 188 bytes in 2 blocks
==1739==    still reachable: 400 bytes in 4 blocks
==1739==                       of which reachable via heuristic:
==1739==                         stdstring          : 44 bytes in 1 blocks
==1739==         suppressed: 0 bytes in 0 blocks
==1739== Reachable blocks (those to which a pointer was found) are not shown.
==1739== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==1739== 
==1739== For lists of detected and suppressed errors, rerun with: -s

Run Code Online (Sandbox Code Playgroud)

导致它的代码只是输入文件无效时引发的常规异常。异常被正确捕获,如下所示:

==1739== HEAP SUMMARY:
==1739==     in use at exit: 588 bytes in 6 blocks
==1739==   total heap usage: 52 allocs, 46 frees, 99,206 bytes allocated
==1739== 
==1739== 44 bytes in 1 blocks are possibly lost in loss record 3 of 6
==1739==    at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1739==    by 0x4C20378: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1739==    by 0x4C03187: std::logic_error::logic_error(char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1739==    by 0x4C0325C: std::invalid_argument::invalid_argument(char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1739==    by 0x10FB6D: lab2::cryptoEngine::CBCCryptoEngine::encrypt() (CBCCryptoEngine.cpp:39)
==1739==    by 0x10E355: main (main.cpp:135)
==1739== 
==1739== 144 bytes in 1 blocks are possibly lost in loss record 4 of 6
==1739==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1739==    by 0x4BDB1F3: __cxa_allocate_exception (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1739==    by 0x10FB5B: lab2::cryptoEngine::CBCCryptoEngine::encrypt() (CBCCryptoEngine.cpp:39)
==1739==    by 0x10E355: main (main.cpp:135)
==1739== 
==1739== LEAK SUMMARY:
==1739==    definitely lost: 0 bytes in 0 blocks
==1739==    indirectly lost: 0 bytes in 0 blocks
==1739==      possibly lost: 188 bytes in 2 blocks
==1739==    still reachable: 400 bytes in 4 blocks
==1739==                       of which reachable via heuristic:
==1739==                         stdstring          : 44 bytes in 1 blocks
==1739==         suppressed: 0 bytes in 0 blocks
==1739== Reachable blocks (those to which a pointer was found) are not shown.
==1739== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==1739== 
==1739== For lists of detected and suppressed errors, rerun with: -s

Run Code Online (Sandbox Code Playgroud)

我不是 100% 确定这意味着什么,如果这甚至是一个问题,因为无论如何内存都会被操作系统回收。但我以前从未见过这种事情,所以想检查一下。

那么,我的问题是,这是由什么引起的?我应该修复它吗?如果是这样,怎么办?

Sam*_*hik 6

std::logic_error的构造函数为“解释字符串”分配了内存。这是what()在异常处理程序中返回给您的(std::invalid_argument继承自std::logic_error)。

请注意,回溯显示了采用 aconst char *作为参数的构造函数重载。const char *如果这个文字被藏起来并从 交还给你,那是可以接受的what()。然而,有各种非物质原因可以解释为什么构造函数被编码为复制“解释字符串”,以便其内容完全由构造函数拥有std::logic_error

您的异常处理程序悄悄地调用exit()并且进程终止。此时valgrind通知您上述分配的内存没有被破坏。这是真的,内存没有被释放。

如果异常处理程序的作用域自然结束(不调用exit()),std::logic_error则析构函数将删除分配的内存,并且每个人都会从此过上幸福的生活。

TLDR:这只是技术内存泄漏。这在技术上是正确的,只是因为地毯是通过调用从流程下拉出来的exit

注意,这里valgrind说的是“可能”而不是“肯定”。毫无疑问,当 valgrind “肯定”声明内存泄漏时,您就会发生内存泄漏。如果只是“可能”,那么可能存在也可能不存在真正的内存泄漏。


n. *_* m. 5

exit或多或少丢失静态存储持续时间的对象不递归拥有的所有内容。当然,这包括堆栈上的事物递归拥有的所有内容,还包括活动异常对象(其内存以未指定的方式分配)。std::string在这种特殊情况下,您会丢失活动异常对象所拥有的缓冲区。

如果您关心此类事情,请不要exit在事情中间使用。重新抛出异常,将其捕获main,让处理程序完成,然后调用exit或者自然退出main)。您可能不应该这样做,因为这不是真正的泄漏(即程序仍在运行时没有分配和丢失内存)。