处理的异常可能导致内存泄漏? (使用调用 exit() 的异常处理。)
Possible memory leak from a handled exception? (With exception handling that calls exit().)
我正在开发一个 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
导致它的代码只是在输入文件无效时抛出的常规异常。像这样正确捕获异常:
try {
engine.encrypt(bad_argument); // Placeholder. The exception type stands, though...
}
catch (const std::invalid_argument &e) {
std::cerr << "Exception while encrypting file: " << e.what() << std::endl;
delete (engine);
exit(EXIT_FAILURE);
}
我不是 100% 确定它是什么意思,如果它甚至是一个问题,因为无论如何内存都会被 OS 回收。但是我从来没有见过这种东西,想看看。
所以,我的问题是,它是由什么引起的?我应该修理它吗?如果可以,怎么做?
exit
或多或少会丢失静态存储持续时间对象不递归拥有的所有内容。当然,这包括堆栈上事物递归拥有的所有内容,还包括活动异常对象(其内存以未指定的方式分配)。在这种特殊情况下,您丢失了一个由活动异常对象拥有的 std::string
拥有的缓冲区。
如果您关心这些事情,请不要在事情中间使用 exit
。重新抛出异常,在 main
中捕获它,让处理程序完成,然后 然后 调用 exit
(或者自然地退出 main
)。你可能不应该,因为这不是真正的泄漏(即程序 没有分配和丢失内存,而它仍然是 运行)。
std::logic_error
's constructor 为“解释字符串”分配了内存。这对你来说是 what()
returns,在异常处理程序中(std::invalid_argument
继承自 std::logic_error
)。
观察回溯显示构造函数重载采用 const char *
作为参数。如果那个文字 const char *
被藏起来,然后从 what()
交还给你,那是可以接受的。然而,构造函数被编码为复制“解释性字符串”以使其内容完全由构造的 std::logic_error
.
拥有的原因有很多。
您的异常处理程序悄悄地调用了 exit()
并且进程终止了。此时 valgrind
通知您上述分配的内存未被破坏。这是真的,内存没有被释放。
如果您的异常处理程序的作用域自然结束(不调用 exit()
),std::logic_error
的析构函数会删除分配的内存,从此以后每个人都会过上幸福的生活。
TLDR:这只是技术性内存泄漏。这在技术上是正确的,只是因为地毯是通过调用 exit
.
从过程中拉出来的
请注意,valgrind
说的是“可能”而不是“肯定”。毫无疑问,当 valgrind“肯定”声称存在内存泄漏时,您会发生内存泄漏。如果它只是“可能”,那么可能存在也可能不存在真正的内存泄漏。
我正在开发一个 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
导致它的代码只是在输入文件无效时抛出的常规异常。像这样正确捕获异常:
try {
engine.encrypt(bad_argument); // Placeholder. The exception type stands, though...
}
catch (const std::invalid_argument &e) {
std::cerr << "Exception while encrypting file: " << e.what() << std::endl;
delete (engine);
exit(EXIT_FAILURE);
}
我不是 100% 确定它是什么意思,如果它甚至是一个问题,因为无论如何内存都会被 OS 回收。但是我从来没有见过这种东西,想看看。
所以,我的问题是,它是由什么引起的?我应该修理它吗?如果可以,怎么做?
exit
或多或少会丢失静态存储持续时间对象不递归拥有的所有内容。当然,这包括堆栈上事物递归拥有的所有内容,还包括活动异常对象(其内存以未指定的方式分配)。在这种特殊情况下,您丢失了一个由活动异常对象拥有的 std::string
拥有的缓冲区。
如果您关心这些事情,请不要在事情中间使用 exit
。重新抛出异常,在 main
中捕获它,让处理程序完成,然后 然后 调用 exit
(或者自然地退出 main
)。你可能不应该,因为这不是真正的泄漏(即程序 没有分配和丢失内存,而它仍然是 运行)。
std::logic_error
's constructor 为“解释字符串”分配了内存。这对你来说是 what()
returns,在异常处理程序中(std::invalid_argument
继承自 std::logic_error
)。
观察回溯显示构造函数重载采用 const char *
作为参数。如果那个文字 const char *
被藏起来,然后从 what()
交还给你,那是可以接受的。然而,构造函数被编码为复制“解释性字符串”以使其内容完全由构造的 std::logic_error
.
您的异常处理程序悄悄地调用了 exit()
并且进程终止了。此时 valgrind
通知您上述分配的内存未被破坏。这是真的,内存没有被释放。
如果您的异常处理程序的作用域自然结束(不调用 exit()
),std::logic_error
的析构函数会删除分配的内存,从此以后每个人都会过上幸福的生活。
TLDR:这只是技术性内存泄漏。这在技术上是正确的,只是因为地毯是通过调用 exit
.
请注意,valgrind
说的是“可能”而不是“肯定”。毫无疑问,当 valgrind“肯定”声称存在内存泄漏时,您会发生内存泄漏。如果它只是“可能”,那么可能存在也可能不存在真正的内存泄漏。