C/C++:關於記憶體的一些bug

來源:互聯網
上載者:User

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

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

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

  誰分配,誰釋放

  一個第三方提供的類的對象,每次析構的時候都會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。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.