2011-01-26 54 views
5

在我用C和C++編寫的程序中,我將新建一個對象來完成任務,然後刪除該對象。如何避免當用戶按下ctrl + c下的內存泄漏?

在以後新的對象此刻卻刪除對象之前,如果用戶按下CTRL +Ç突破的過程,這將導致刪除不被調用,發生內存泄漏。

我應該怎麼做才能避免這種情況?

此外,如果內存被操作系統回收,那麼打開的文件又如何?他們是否被操作系統關閉,或者我應該關閉它們嗎?

+0

可有人請她/的Linux/Unix /概括呢? – 2012-11-09 01:19:05

回答

7

在基於虛擬內存的系統中,當進程終止時,所有內存都會返回到操作系統,無論它是否在應用程序代碼中顯式釋放。其他資源也可能不是這樣,但是,您可能想要乾淨地釋放這些資源。在這種情況下,您需要爲SIGINT信號(在Ctrl + C上接收)提供自定義信號處理程序,請參閱。 http://linux.die.net/man/2/sigaction

+0

這是否意味着我不應該在意內存分配?但我發現我的析構函數沒有被調用。也打開的文件被OS關閉了嗎? – PDF1001 2011-01-26 01:16:52

1

當進程由於Ctrl-C或任何其他方式而退出時,OS將回收進程分配的內存。

7

按下Ctrl鍵ÇSIGINT發送給該進程,它默認一大部分,有序的關閉,其中包括拆除內存管理器,並釋放所有分配的堆和棧。如果您需要執行其他任務,則需要安裝SIGINT處理程序並自行執行這些任務。

2

當在Linux控制檯中按下CTRL + C時,SIGINT信號被髮送到應用程序,如果信號沒有處理程序,將終止程序,將所有內存返回到操作系統。這當然會使得釋放內存毫無意義,因爲一旦程序存在,所有的內存都將被釋放。但是,如果您想要處理CTRL + C SIGINT信號(可能會將一些最後的數據寫入文件或進行其他清理),則可以使用函數signal()來安裝在接收到信號時要調用的函數。如果您想了解更多信息,請查看此功能的手冊頁。

2

如果您使用shmget(2)分配了任何SYSV共享內存段,則必須使用shmctl(2)自行清理。

如果您使用shm_open(3)分配了任何POSIX共享內存段,則必須使用shm_unlink(3)自行清理。

SYSV和POSIX共享內存段在過程終止之後仍然存在。您可以使用ipcs(1)工具查看仍然存在的內容。

當然,如果您還沒有使用任何SYSV或POSIX共享內存段,那麼這只是噪聲。 :)

2

如果進程退出,通常不會發生內存泄漏。

您分配的大部分內存將在Ctrl + C上釋放。如果您看到內存使用情況沒有恢復到以前的水平,那幾乎肯定是由緩衝的文件系統塊造成的。

但是,你一定要乾淨的東西,特別是如果你使用的任何其他類型的資源:

  • 在臨時目錄中創建的文件不會被刪除。這包括/ dev/shm,讓這樣的文件可能被認爲是「內存泄漏」。
  • 系統V或POSIX共享內存段將不會扔掉你的進程退出。如果這讓你感到困擾,請特別清理它們。或者,在隨後的運行中清理它們。

一般來說,如果隨後的運行不會泄漏存儲器(持久或半持久對象例如文件)的泄漏也沒關係。所以清理未來運行就足夠了。

試想一個過程,從「cron的」運行每5分鐘,如果它崩潰每次運行並留下一些亂七八糟的,它仍然提供確定每次運行清理從以前崩潰的爛攤子。

0

您訂閱到堆未釋放的塊一個相當普遍的誤解,但在程序中存在的時候仍然可以訪問的泄漏。這不是真的。泄漏塊是那些沒有指針仍然引用的塊,因此它們不能被釋放。通過多年玩弄(和打破)很多完美的內核,我從來沒有設法充分打破虛擬內存管理器,直到它退出後不再回收整個地址空間。除非您正在使用明確標記爲「新的和實驗性」的內核,否則與找到不使用有效虛擬內存管理器的系統相比,獲得彩票的運氣會更好。

不要把克魯夫特在你的代碼只是爲了獲得一個Valgrind的滿分。如果你沒有真正的清理任務做其他比釋放內存仍然具有有效的參考,你不必理會。如果有人向您的程序拋出kill -9,您將無法處理它,並會看到舊的行爲重複。

如果您有文件描述符清理,共享鎖放棄,流清除或其他任何必須發生的事情,所以其他進程不會在你離開時錯過你,通過一切手段來照顧。只是不要添加無用的代碼來解決非問題,這樣做似乎很愚蠢。

注意

這本來將是一個評論,更是遠遠太長,在上一次寫小說一個評論SO皺眉。