程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 更多關於編程 >> C/C++:關於內存的一些bug

C/C++:關於內存的一些bug

編輯:更多關於編程

      從內存管理方面來講,C#是個完美的天堂,你不用像在C++中那樣萬分小心的管理著你的內存;盡管如此,本人還是喜歡C++要多些,正如微軟稱C++為native代碼 - C++對我來講,的確是要更native一些。

      其實,很多時候,C++之於C#,就像手動擋之於自動擋。

      閒話不扯,一般情況下,我們會碰到的內存問題有使用未初始化的指針,使用空指針,釋放已經釋放過的內存等等。最近工作中也遇到兩個內存相關的問題,覺得記下來還是有些價值的。

      誰分配,誰釋放

      一個第三方提供的類的對象,每次析構的時候都會crash。仔細檢查後發現,我們在此之前new了一塊內存並將指針設給了該對象的一個成員(object.p)。於是懷疑該類在析構函數中試圖delete該塊內存。 試了一下在析構之前先將Object.p置0, 問題果然不再存在,於是基本可以確定是這個原因了。

      這裡其實有兩個問題,一是我們的代碼沒有釋放自己分配的內存;二是第三方庫的代碼,不應該delete不是自己分配的內存。誰分配,誰釋放是一個相當重要的原則,一個試圖釋放使用者new出來的內存的第三方庫,至少存在以下問題:

      一般情況下,使用著會釋放自己new出來的內存,那麼這裡就會出現二次釋放的問題。

      如果任何一方重載了operator new和operator delete,定義了自己的內存池,那麼基本就是雞同鴨講了。

      如果傳給你的是一個棧上的對象呢,你也delete?

      無意中被破壞的內存

      我們有一個基於內存的transaction manager,基本原理就是,每做一個數據修改就會將被修改過的內存備份起來,然後undo的時候,將備份的數據再覆蓋回來。當然,這裡需要被備份的內存,使用一種特殊的方式分配的,我們稱之為transacted memory。考慮如下流程:

      做一個數據修改,比如畫一個圓

      該操作需要將提供畫圓函數的DLL動態加載進來

      在該DLL加載及初始話化過程中,創建了一個transacted memory,比如說一個std::map

      畫圓完成後,做一個Undo操作

      於是該新畫出來的圓又被原內存覆蓋回去了,而同時,在加載DLL過程中分配的那個std::map也被覆蓋回去了,注意,加載DLL的過程並不會被undo,於是,當程序再次試圖訪問該map時出錯,因為該map的內容已經完全面目全非了。

      這個bug花了我4、5個小時才發現問題所在,解決方法其實也很簡單,那就是避免在初始化DLL時分配transacted memory。

    1. 上一頁:
    2. 下一頁:
    Copyright © 程式師世界 All Rights Reserved