国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C/C++內(nèi)存泄漏原因分析與應對方法

這篇具有很好參考價值的文章主要介紹了C/C++內(nèi)存泄漏原因分析與應對方法。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

內(nèi)存泄漏

一、內(nèi)存泄漏的危害:

內(nèi)存泄漏會導致當前應用程序消耗更多的內(nèi)存,使得其他應用程序可用的內(nèi)存更少了。

如果有個進程可用的內(nèi)存不夠,就會觸發(fā)Linux操作系統(tǒng)的直接/后臺內(nèi)存回收(即將一些內(nèi)存頁的數(shù)據(jù)寫到磁盤里,那么該頁也就可用了,臟頁回寫)。雖然后臺回收是異步的不阻塞當前進程,但是內(nèi)存還是不夠會觸發(fā)直接內(nèi)存回收,最后內(nèi)存泄漏積累到一定程度,會直接觸發(fā)OOM,該機制會殺掉那些實時占用內(nèi)存大的進程

而且,即使沒有OOM,無論是直接回收還是后臺回收,都需要磁盤I/O而且需要多執(zhí)行額外的回收線程,使系統(tǒng)性能下降。

  • 后臺內(nèi)存回收(kswapd):在物理內(nèi)存緊張的時候,會喚醒 kswapd 內(nèi)核線程來回收內(nèi)存,這個回收內(nèi)存的過程異步的,不會阻塞進程的執(zhí)行。
  • 直接內(nèi)存回收(direct reclaim):如果后臺異步回收跟不上進程內(nèi)存申請的速度,就會開始直接回收,這個回收內(nèi)存的過程是同步的,會阻塞進程的執(zhí)行,這個過程比較慢,導致CPU占用率飆升。

如果直接內(nèi)存回收后,空閑的物理內(nèi)存仍然無法滿足此次物理內(nèi)存的申請,那么內(nèi)核就會放最后的大招了 ——觸發(fā) OOM (Out of Memory)機制。

還有資源泄漏:

比如沒有關閉文件,程序提前return或報錯或忘記關閉,則可能導致想寫入文件的數(shù)據(jù)沒有真正落盤,從而丟失數(shù)據(jù)。

二、內(nèi)存泄漏舉例:

1,在free()前就返回了,或者是報錯并退出程序。要在程序的所有路徑上(if()的各個條件)都執(zhí)行資源釋放操作。

2,在析構函數(shù)中未執(zhí)行內(nèi)存釋放操作。在構造函數(shù)中申請了堆內(nèi)存或者打開了文件,在析構函數(shù)中忘了釋放資源。

3,基類的析構函數(shù)未聲明為虛函數(shù)

析構函數(shù)如果不聲明為虛函數(shù),可能會導致多態(tài)對象在刪除時無法正確調用派生類的析構函數(shù)(如果子類構造函數(shù)里malloc()了內(nèi)存,然后在析構函數(shù)里free()),從而導致內(nèi)存泄漏。

4,shared_ptr循環(huán)引用導致內(nèi)存泄漏,用weak_ptr解決。如下示例:

class Contro {
private:
	double* p;
 public:
  Contro() {
  	 p = new double[10];
  }

  ~Contro() {
  	 delete[] p;
     std::cout << "in ~Contro" << std::endl;
  }
// 類內(nèi)類
  class SubContro {
   public:
    SubContro() {
  	  p = new double[10];
  }

    ~SubContro() {
      delete[] p;
      std::cout << "in ~SubContro" << std::endl;
    }

    std::shared_ptr<Contro> controller_;
  };

  std::shared_ptr<SubContro> sub_controller_;
};

int main() {
  auto contro = std::make_shared<Contro>();
  auto sub_contro = std::make_shared<Contro::SubContro>();

  contro->sub_controller_ = sub_contro;
  sub_contro->controller_ = contro;
  // 打印引用計數(shù)
  std::cout << "contro use_count: " << contro.use_count() << std::endl;
  std::cout << "sub_contro use_count: " << sub_contro.use_count() << std::endl;
  return 0;
}

發(fā)生循環(huán)引用,兩個的引用計數(shù)輸出都是2,所以main函數(shù)結束的時候,引用計數(shù)沒有減為0,就不會調用二者的析構函數(shù),導致資源泄漏
將SubContro類里的shared_ptr改成weak_ptr即可,后者不會增加引用計數(shù),因此兩個智能指針的引用計數(shù)都是1,然后main結束的時候,引用計數(shù)減少為0,然后執(zhí)行析構函數(shù),此時不會發(fā)生內(nèi)存泄漏,輸出如下:

contro use_count: 1
sub_contro use_count: 2
in ~Contro
in ~SubContro

三、避免內(nèi)存泄漏的手段:

1. 靜態(tài)代碼檢查工具
(1)對于大型項目,可以使用靜態(tài)代碼分析工具

像開源的有codechecker軟件,集成了一些靜態(tài)代碼分析的工具

靜態(tài)代碼檢查工具會從詞法、語法、語義等多維度去對工程代碼掃描分析,發(fā)現(xiàn)可能存在的問題,比如變量未定義、類型不匹配、變量作用域問題、數(shù)組下標越界、內(nèi)存泄露等問題。

既然是靜態(tài),那么就不是運行時。但是是編譯前還是編譯后還是編譯中?

其實都有,像商業(yè)軟件“啄木鳥”是給源文件就行,然后它會在編譯的過程中去檢測語法,詞法,以及最后生成的二進制。

代碼靜態(tài)分析(SAST):可以簡單的理解為在不執(zhí)行程序的情況下,對源代碼, 中間代碼或者二進制代碼進行分析的技術

(2)編譯成專門的內(nèi)存泄漏檢查版本。

可以把整個項目編譯成檢查內(nèi)存泄漏版本的可執(zhí)行文件,然后運行相關工具,并且讓運行結果專門記錄內(nèi)存泄漏,將泄漏結果放在對應輸出文件上。

比如opengauss就有,參考鏈接:http://t.csdn.cn/DqusO

編譯openGauss時,編譯一個memcheck版的,然后通過跑fastcheck_single來發(fā)現(xiàn)代碼中的內(nèi)存問題。 編譯方式和編譯普通的openGauss基本一致,只是在configure時,添加一個 --enable-memory-check 參數(shù),編譯出來的就是memcheck版本的openGauss。

但是編譯前,要設置一些環(huán)境變量,ulimit -v unlimited

ulimit命令:用于控制shell程序的資源, -v <虛擬內(nèi)存大小>  指定可使用的虛擬內(nèi)存上限,單位為KB。

因為可能有內(nèi)存泄漏,所以就設置虛擬內(nèi)存大小為不受限制。

2. valgrind工具

可以安裝valgrind工具,指定工具--tool=memcheck,也可以指定輸出日志,否則輸出在終端

--log-file=leak1.log

對可執(zhí)行文件a.out,執(zhí)行如下命令:

valgrind --log-file=valgrind.log --tool=memcheck --leak-check=full --show-leak-kinds=all ./a.out

如下可以看到總的malloc和free的次數(shù),以及被申請的字節(jié)數(shù),在每一個內(nèi)存泄漏的地方,也會顯示函數(shù)調用堆棧,便于追蹤:
C/C++內(nèi)存泄漏原因分析與應對方法,C++學習筆記,c語言,c++,操作系統(tǒng)底層
(注:圖片相關函數(shù)做了打碼處理)

這個工具的用法還挺多,可以參考https://zhuanlan.zhihu.com/p/92074597

3. GDB調試

比如我們懷疑FUNC()函數(shù)有內(nèi)存泄漏。

1,比如給某個函數(shù)FUNC()打斷點,進入后這個函數(shù)里面也調用了很多其他函數(shù)func1,func2…,懷疑這些調用里面,或者外面有內(nèi)存泄漏。我們可以給malloc()和free()打斷點(或者是自己封裝的函數(shù)),當malloc()命中后,bt查看棧幀,就知道哪個函數(shù)調用了malloc,申請了堆內(nèi)存,比如func1,這樣可以重點關注該函數(shù)。

2,然后看后面free()斷點有沒有命中,命中的時候查看棧幀,如果不是這個函數(shù)func1調用的free(),那說明這個函數(shù)沒有執(zhí)行free。

3,此外,可以追蹤指針p的值(watch p),看看它有沒有變?yōu)?x0,被釋放且被賦值為0x0,才不會成為懸空指針。

4,在函數(shù)FUNC()的末尾,還可以看看malloc和free的斷點命中次數(shù),如果次數(shù)一樣,那沒問題。文章來源地址http://www.zghlxwxcb.cn/news/detail-564355.html

到了這里,關于C/C++內(nèi)存泄漏原因分析與應對方法的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 首次設置貝爾金無線路由出錯原因分析與解決方法

    ? 一、檢查線路、拓撲連接和面板燈 先用一臺電腦撥號上網(wǎng),如果行,可以排除線路故障。之后只將一臺電腦接到無線路由器,路由器接MODEM,檢查無線路由器電源接口、廣域網(wǎng)端口和局域網(wǎng)端口連接情況和對應的面板燈,在物理連接正常時,面板的電源燈、Internet燈和已用

    2024年02月05日
    瀏覽(44)
  • 金浪路由器遭入侵的原因分析及防范方法

    ? ? 一、通過分析發(fā)現(xiàn),這些數(shù)據(jù)包是內(nèi)網(wǎng)電腦A發(fā)送給外網(wǎng)電腦B的,發(fā)送速度不小于每秒l萬個,將該電腦斷開后,問題解決,這時我們可以在電腦A上安裝Sniffer,通過抓包分析發(fā)現(xiàn),一旦連接網(wǎng)絡,該電腦主動攻擊外網(wǎng)電腦B,原來,這臺電腦成了一次攻擊的傀儡機。 二、攻

    2024年02月05日
    瀏覽(21)
  • 阿爾法路由器無法Telnet的原因分析以及解決方法

    ? 一、組網(wǎng)環(huán)境 在阿爾法路由器的組網(wǎng)環(huán)境中,當配置完成后,所有的業(yè)務運行正常,通過外網(wǎng)或者阿爾法A上可以Ping通阿爾法B,但是無法Telnet到阿爾法B,如果先從外網(wǎng)登陸上,則能夠Telnet到路由器。 二、故障分析 1、分析Telnet與Ping的區(qū)別在于:Ping可以直接在阿爾法B接口

    2024年02月05日
    瀏覽(40)
  • 飛魚星路由器無線傳感器故障的原因分析及解決方法

    當網(wǎng)絡或系統(tǒng)出現(xiàn)故障時,網(wǎng)絡故障管理便成為管理員首要用到的工具,因此,故障管理事實上是整個網(wǎng)絡管理的重中之重,由于網(wǎng)絡故障涉及到不同廠商,不同類型設備,涉及復雜的網(wǎng)絡拓撲結構,涉及不同組織對故障類型的不同定位規(guī)則,本文就以飛魚路由器為大家無線

    2024年02月05日
    瀏覽(21)
  • 網(wǎng)上鄰居打開很慢(默認會延遲30秒)的原因分析及解決方法

    有很多使用windows XP用戶反映在打開網(wǎng)上鄰居很慢,開機也沒有開太多的運行程序,怎么會感覺瀏覽網(wǎng)上鄰居很慢呢?其實這只是系統(tǒng)的一種設置,下面來看看打開網(wǎng)上鄰居很慢的原因以及解決途徑。 一、網(wǎng)上鄰居打開很慢的原因 在WinXP和Win2000中瀏覽網(wǎng)上鄰居時系統(tǒng)默認會延

    2024年02月06日
    瀏覽(38)
  • Ping 出現(xiàn)TTL expired in transit錯誤原因分析及解決方法

    寢室網(wǎng)絡割接導致本本上不了網(wǎng)了,于是在其他地方ping本本的IP來試,結果出現(xiàn)了TTL expired in transit的提示,這種提示并不常見,如下圖所示: ping 和 tracert 的結果 用tracert來看路由狀況,原來是出現(xiàn)路由環(huán)路導致TTL超時。 出現(xiàn)路由環(huán)路的解決方法是重新設定路由配置,避免環(huán)

    2024年02月06日
    瀏覽(19)
  • FANUC機器人SRVO-105和SRVO-067故障報警原因分析及處理方法

    FANUC機器人SRVO-105和SRVO-067故障報警原因分析及處理方法

    如下圖所示,公司的一臺機器人在正常工作時突然報警SRVO-105門打開或緊急停止,同時還有SRVO-067 OHAL2報警(G:1 A:2),按Reset鍵無法消除報警, 那么遇到這種情況,首先,我們來看一下報警說明書上的解釋: 首先看一下SRVO-105報警: 總結: 報警原因:控制裝置的柜門打開

    2024年02月08日
    瀏覽(95)
  • 常見的內(nèi)存泄漏原因和解決方案

    1.全局引用 問題:在JavaScript代碼中,使用全局變量或全局對象來保存對DOM元素或其他對象的引用,這可能導致內(nèi)存泄漏。 解決方案:避免使用全局變量或全局對象,改用合適的作用域來管理變量和對象的生命周期。確保在不再需要時正確地釋放這些引用。 2.事件監(jiān)聽器 問題

    2024年02月13日
    瀏覽(36)
  • Handler內(nèi)存泄漏原因及解決方案

    在Activity中,將Handler聲明成非靜態(tài)內(nèi)部類或匿名內(nèi)部類,這樣Handle默認持有外部類Activity的引用。如果Activity在銷毀時,Handler還有未執(zhí)行完或者正在執(zhí)行的Message,而Handler又持有Activity的引用,導致GC無法回收Activity,導致內(nèi)存泄漏。如以下兩種情形可能導致內(nèi)存泄漏 1、在Act

    2024年02月16日
    瀏覽(51)
  • QT--崩潰原因分析

    QT--崩潰原因分析

    本文為學習記錄,若有錯誤,請聯(lián)系作者,謙虛受教。 你從來來去自由,若你不想要了跑開便是。 發(fā)布的客戶版本里分析崩潰原因,便于解決問題。 在自己QT安裝的目錄下,例如:D:QtQt5.12.3Toolsmingw730_32bin,找到adde2line.exe。 將add2line.exe復制到自己發(fā)布的版本中。 在代碼

    2024年02月13日
    瀏覽(27)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包