我正在開發一個 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% 確定這意味著什么,如果它甚至是一個問題,因為無論如何記憶體都會被作業系統回收。但是我以前從未見過這種東西,并想檢查一下。
所以,我的問題是,它是由什么引起的?我應該修復它嗎?如果是這樣,怎么做?
uj5u.com熱心網友回復:
std::logic_error的建構式為“解釋字串”分配記憶體。這是在例外處理程式(繼承自)what()中回傳給您的。std::invalid_argumentstd::logic_error
請注意,回溯顯示了建構式多載,該建構式采用 aconst char *作為引數。如果那個文字const char *被藏起來,并從what(). 然而,建構式被編碼為復制“解釋字串”以使其內容完全由建構式擁有,有各種非物質原因std::logic_error。
您的例外處理程式悄悄地呼叫exit()并且行程終止。此時valgrind通知您上述分配的記憶體沒有被破壞。這是真的,記憶體沒有被釋放。
如果您的例外處理程式的范圍自然結束(不呼叫exit()),std::logic_error' 的解構式會洗掉分配的記憶體,并且每個人都會從此過上幸福的生活。
TLDR:這只是技術上的記憶體泄漏。這在技術上是正確的,只是因為地毯是通過呼叫從程序中拉出來的exit。
請注意,valgrind說“可能”而不是“肯定”。毫無疑問,當 valgrind “肯定”聲稱有記憶體泄漏時,您就有了記憶體泄漏。如果只是“可能”,那么可能存在也可能不存在真正的記憶體泄漏。
uj5u.com熱心網友回復:
exit或多或少地丟失所有不是由靜態存盤持續時間的物件遞回擁有的東西。當然,這包括堆疊上的事物遞回擁有的所有內容,還包括活動例外物件(其記憶體以未指定的方式分配)。std::string在這種特殊情況下,您丟失了由活動例外物件擁有的緩沖區。
如果您關心這些事情,請不要exit在中間使用。重新拋出例外,將其捕獲main,讓處理程式完成,然后呼叫exit(或main自然退出)。您可能不應該這樣做,因為這不是真正的泄漏(即程式仍在運行時沒有分配和丟失記憶體)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/465277.html
