最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2023年07月14日 10:08:08   作者:魚在樹上飛  
內(nèi)存泄漏會導致當前應用程序消耗更多的內(nèi)存,使得其他應用程序可用的內(nèi)存更少了,那么為什么會內(nèi)存泄漏,我們應該怎樣應對內(nèi)存泄漏,所以接下來就給大家詳細介紹一下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)對象在刪除時無法正確調(diào)用派生類的析構函數(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];
  }
  ~Controller() {
  	 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<Controller::SubContro>();
  contro->sub_controller_ = sub_contro;
  sub_contro->controller_ = contro;
  // 打印引用計數(shù)
  std::cout << "controller use_count: " << contro.use_count() << std::endl;
  std::cout << "sub_controller use_count: " << sub_contro.use_count() << std::endl;
  return 0;
}

發(fā)生循環(huán)引用,兩個的引用計數(shù)輸出都是2,所以main函數(shù)結束的時候,引用計數(shù)沒有減為0,就不會調(diào)用二者的析構函數(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)代碼分析工具

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

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

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

代碼靜態(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í)行命令如下:

valgrind  --tool=memcheck ./a.out

如下可以看到malloc和free的次數(shù),以及被申請的字節(jié)數(shù):

HEAP SUMMARY:
in use at exit: 8 bytes in 1 blocks
total heap usage: 1 allocs, 0 frees, 8 bytes allocated

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

3. GDB調(diào)試

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

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

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

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

4,在函數(shù)FUNC()的末尾,還可以看看malloc和free的斷點命中次數(shù),如果次數(shù)一樣,那沒問題。

以上就是C/C++內(nèi)存泄漏原因分析與應對方法的詳細內(nèi)容,更多關于C/C++內(nèi)存泄漏的資料請關注腳本之家其它相關文章!

相關文章

  • QT設置widget背景圖片不影響widget內(nèi)其他控件背景的方法

    QT設置widget背景圖片不影響widget內(nèi)其他控件背景的方法

    這篇文章主要給大家介紹了關于QT設置widget背景圖片不影響widget內(nèi)其他控件背景的方法,軟件的界面為了更直觀或美觀,常常需要通過圖片來表達,需要的朋友可以參考下
    2023-06-06
  • 使用C語言繪制統(tǒng)計圖中的餅圖

    使用C語言繪制統(tǒng)計圖中的餅圖

    常用的統(tǒng)計圖有條形圖、柱形圖、折線圖、曲線圖、餅圖、環(huán)形圖、扇形圖,本文主要為大家詳細介紹了如何使用使用C語言繪制統(tǒng)計圖中的餅圖,希望對大家有所幫助
    2024-02-02
  • 基于樹莓派的語音機器人

    基于樹莓派的語音機器人

    這篇文章主要為大家詳細介紹了基于樹莓派的語音機器人,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • c++ static詳細使用分析

    c++ static詳細使用分析

    在C++中,static是一個關鍵字,用于聲明靜態(tài)成員、靜態(tài)局部變量以及靜態(tài)函數(shù),這篇文章主要介紹了c++ static詳細分析,需要的朋友可以參考下
    2024-05-05
  • C++ 類模板、函數(shù)模板全特化、偏特化的使用

    C++ 類模板、函數(shù)模板全特化、偏特化的使用

    這篇文章主要介紹了C++ 類模板、函數(shù)模板全特化、偏特化的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-02-02
  • Qt窗口開發(fā)之QFileDialog文件對話框代碼示例

    Qt窗口開發(fā)之QFileDialog文件對話框代碼示例

    QFileDialog是一個用于選擇文件或文件夾的對話框類,它是Qt框架提供的,該類提供了一種方便的方式來打開、保存和選擇文件或文件夾,這篇文章主要介紹了Qt窗口開發(fā)之QFileDialog文件對話框的相關資料,需要的朋友可以參考下
    2025-12-12
  • 在C++?中慎用setjmp和longjmp解析

    在C++?中慎用setjmp和longjmp解析

    setjmp和longjmp是C語言中用于實現(xiàn)非局部跳轉的函數(shù),setjmp和longjmp 是 C 語言中一個很強大的函數(shù),這篇文章主要介紹了在C++?中慎用setjmp和longjmp的相關知識,需要的朋友可以參考下
    2023-06-06
  • C/C++中虛基類詳解及其作用介紹

    C/C++中虛基類詳解及其作用介紹

    這篇文章主要介紹了C/C++中虛基類的詳解及其作用介紹,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • 源碼分析C++是如何實現(xiàn)string的

    源碼分析C++是如何實現(xiàn)string的

    我們平時使用C++開發(fā)過程中或多或少都會使用std::string,但您了解string具體是如何實現(xiàn)的嗎,本文小編就帶大家從源碼角度分析一下
    2023-04-04
  • C++深入講解哈夫曼樹

    C++深入講解哈夫曼樹

    給定N個權值作為N個葉子結點,構造一棵二叉樹,若該樹的帶權路徑長度達到最小,稱這樣的二叉樹為最優(yōu)二叉樹,也稱為哈夫曼樹(Huffman Tree)。哈夫曼樹是帶權路徑長度最短的樹,權值較大的結點離根較近
    2022-05-05

最新評論

富源县| 镇康县| 桦甸市| 清水河县| 响水县| 三原县| 阳江市| 嘉义县| 鹤庆县| 大姚县| 阳泉市| 台东市| 赤峰市| 崇仁县| 慈利县| 景德镇市| 京山县| 仁化县| 武威市| 老河口市| 遵义市| 定兴县| 顺平县| 徐闻县| 阿合奇县| 定兴县| 西安市| 鞍山市| 绿春县| 宜宾县| 遂溪县| 边坝县| 湖南省| 静海县| 阿荣旗| 深水埗区| 柯坪县| 山阳县| 大悟县| 兰考县| 台东市|