在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何處理服務(wù)存在內(nèi)存泄漏問題?

GReq_mcu168 ? 來源:玩轉(zhuǎn)單片機(jī) ? 作者:玩轉(zhuǎn)單片機(jī) ? 2021-03-02 10:23 ? 次閱讀

上周像往常一樣例行檢查線上機(jī)器性能,突然發(fā)現(xiàn)一個服務(wù)的內(nèi)存使用率是這樣的:

很顯然該服務(wù)存在內(nèi)存泄漏問題,趕緊排查問題。

問題排查

首先確定內(nèi)存泄漏問題出現(xiàn)的時間,發(fā)現(xiàn)在該時間點的上線有兩次代碼提交,其中一個就是我的。于是立刻排查這兩次代碼的改動,確定了另一個同事的代碼不可能會有內(nèi)存問題后(因為另一個同事的上線僅僅修改了配置)我知道肯定是自己的代碼出現(xiàn)了問題。

確定了問題所在后趕緊把自己的代碼回滾掉,接下來就可以放心debug了。

Debug

什么是內(nèi)存泄漏?

簡單的講就是程序員申請的內(nèi)存在使用完后沒有還給操作系統(tǒng),由于筆者使用的是C++語言,因此內(nèi)存泄漏一般是這樣的:

obj* o = new obj(); ... // 使用完obj后沒有delete

肯定有什么地方申請了內(nèi)存后沒有調(diào)用delete釋放內(nèi)存。

在這里介紹一下筆者的代碼改動,我的任務(wù)其實是重構(gòu)一段代碼,把這段代碼并行化。也就是舊的邏輯是在一個線程中串行執(zhí)行的,現(xiàn)在我要把這段邏輯放到兩個線程中并行執(zhí)行,這是最讓人頭疼的任務(wù)之一,并行化改造是比較容易出bug的。

接下來梳理了一遍中所有內(nèi)存的申請和釋放,這其中包括:

使用new/delete分配釋放的內(nèi)存

使用內(nèi)存池分配釋放的內(nèi)存

仔細(xì)梳理一遍后沒有發(fā)現(xiàn)任何問題,該釋放的內(nèi)存都已經(jīng)釋放掉了,這時筆者已經(jīng)開始懷疑人生了 :) ,很顯然還有一段沒有注意到的地方出現(xiàn)了問題,這是必然的,雖然知道問題必然出現(xiàn)在改動的這些代碼里但是我并不能確定出現(xiàn)的位置。

沒有辦法,到這里基本上已經(jīng)要放棄自己人肉debug了,想利用一些內(nèi)存檢測工具來幫助自己確定問題。

常見的內(nèi)存泄漏檢測工具包括valgrind、gperftools等,valgrind的好處在于無需重新編譯代碼即可進(jìn)行內(nèi)存檢測,但是缺點是會使得程序運行非常緩慢,官方文檔給的說法是會比正常的程序運行慢20-30倍;gperftools則需要重新編譯可執(zhí)行程序。這些工具需要下載安裝測試,其中還涉及到申請機(jī)器權(quán)限等問題,筆者覺得還是比較麻煩,況且這個問題也不是大海撈針一樣,問題肯定出在了并行化的這段代碼中。

到這里我決定再換一個思路來排查問題,既然代碼重構(gòu)后開始并行執(zhí)行,那么出現(xiàn)問題大概率是因為多線程問題,遇到多線程問題首先重點排查的就是線程間的共享數(shù)據(jù)。

多線程問題的關(guān)鍵——共享數(shù)據(jù)

我們知道如果線程之間沒有共享數(shù)據(jù)那么就不會有線程安全問題,我們使用的鎖、信號量、條件變量等其實都是用來保護(hù)共享數(shù)據(jù)的,比如鎖通常是用來包括臨界區(qū)的,臨界區(qū)中的代碼操作的就是線程共享數(shù)據(jù);信號量使用的一個經(jīng)典場景就是生產(chǎn)者消費者問題,生產(chǎn)者線程以及消費者線程都會操作同一個隊列,這里的隊列就是共享數(shù)據(jù)。

沿著這個思路開始找在兩個線程中都使用到的共享數(shù)據(jù),果不其然,在一個角落中發(fā)現(xiàn)了這樣一段代碼:

auto* pb = global->mutable_obj();

這是分配protobuf對象的一段代碼,protobuf是Google開發(fā)是一種類似于JSON、XML的技術(shù),因此常用于網(wǎng)絡(luò)通信和數(shù)據(jù)交換等場景,比如RPC等。

如果你不了解protobuf也沒有關(guān)系,實際上上面的這段代碼的要做的事情是這樣的:

if (global->obj == NULL) { global->obj = new obj();}return global->obj;

值得注意的是這段代碼現(xiàn)在會在兩個線程中執(zhí)行,顯然問題就出現(xiàn)在了這里。

那么問題是怎么出現(xiàn)的呢?

我們假設(shè)有兩個線程,線程A和線程B,當(dāng)這樣一段代碼在線程AB中同時執(zhí)行時可能會有以下場景:

線程A拿到global->obj并檢測到此時的global->obj為空,因此決定為其分配內(nèi)存,但不巧的是此時發(fā)生線程切換,線程A在為global->obj分配內(nèi)存前被暫停運行,如下所示:

if (global->obj == NULL) { <------- 線程切換,線程A被暫停執(zhí)行 global->obj = new obj();}return global->obj;

線程A被暫停運行后線程B開始執(zhí)行,這段代碼同樣會在線程B中執(zhí)行一遍,因此線程B會首先檢查global->obj發(fā)現(xiàn)為空,因此為global->obj分配內(nèi)存,分配完內(nèi)存后發(fā)生線程切換,線程B被暫停運行,如下所示:

if (global->obj == NULL) { global->obj = new obj(); <------- 線程切換,線程B被暫停執(zhí)行 }return global->obj;

線程B被暫停運行后調(diào)度器決定重新運行線程A,此時線程A開始從被中斷的地方繼續(xù)運行,還記得線程A是從哪里被中斷的嗎,沒錯,就是在為global->obj分配內(nèi)存前被中斷的,此時線程A繼續(xù)運行,也就是說global->obj = new obj()這段代碼又被執(zhí)行了一次,雖然線程B已經(jīng)為global->obj分配了內(nèi)存。

Oops,典型的內(nèi)存泄漏,線程B分配的內(nèi)存再也無法被正常釋放掉了。

至此,我們已經(jīng)找到了問題的原因,罪魁禍?zhǔn)拙褪枪蚕頂?shù)據(jù),關(guān)鍵的一點是要意識到你的線程會隨時被中斷執(zhí)行,CPU會隨時切換到其它線程。

代碼修復(fù)也非常簡單,再新增一個變量,兩個線程不在使用共享數(shù)據(jù),到這里問題就解決了,從發(fā)現(xiàn)問題到完成修復(fù)耗時大概4小時。

經(jīng)驗教訓(xùn)

代碼的并行化重構(gòu)是一件非常棘手的任務(wù),很容易出現(xiàn)線程安全問題,解決線程安全問題首先要考慮的不是要不要加鎖,而是多個線程是否真的有必要使用共享數(shù)據(jù),沒有必要的話多個線程操作私有數(shù)據(jù)根本就不會出現(xiàn)線程安全問題。

當(dāng)出現(xiàn)線程安全問題時,第一時間重點排查線程使用的共享數(shù)據(jù)。

內(nèi)存泄漏檢測工具

雖然這些沒有使用檢測工具全靠人肉debug其實還是因為問題排查范圍比較小,如果我們根本就不知道問題出現(xiàn)在了那次代碼改動那么檢測工具就非常重要了,在這里簡單介紹一下valgrind的使用,詳細(xì)的介紹請參考官方文檔。

假設(shè)有這樣一段問題代碼:

#include voidf(void) { int* x = malloc(10 * sizeof(int)); x[10] = 0; // 問題1: 越界} // 問題2: 內(nèi)存泄漏,x沒有被釋放掉 intmain(){ f(); return 0;}

這段代碼中有兩個問題:一個是數(shù)據(jù)的越界訪問;另一個是內(nèi)存泄漏。將該程序編譯為myprog。

接下來使用valgrind來檢查該程序,使用以下命令:

valgrind --leak-check=yes myprog

運行完成后valgrind會給出檢測報告,關(guān)于程序越界訪問會給出這樣的輸出:

==19182== Invalid write of size 4==19182== at 0x804838F: f (example.c:6)==19182== by 0x80483AB: main (example.c:11)==19182== Address 0x1BA45050 is 0 bytes after a block of size 40 alloc'd==19182== at 0x1B8FF5CD: malloc (vg_replace_malloc.c:130)==19182== by 0x8048385: f (example.c:5)==19182== by 0x80483AB: main (example.c:11)

第一行告訴你代碼中存在Invalid write,也就是無效的寫,并給出了問題出現(xiàn)的位置。

關(guān)于內(nèi)存泄漏問題會給出這樣的輸出:

==19182== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1==19182== at 0x1B8FF5CD: malloc (vg_replace_malloc.c:130)==19182== by 0x8048385: f (example.c:5)==19182== by 0x80483AB: main (example.c:11)

這里第一行報告了內(nèi)存"definitely lost",也就是說一定會存在內(nèi)存泄漏,并給出了問題出現(xiàn)的位置。

實際上除了"definitely lost",valgrind還會給出"probably lost"的報告,這兩種報告的含義是這樣的:

"definitely lost":你的程序一定存在內(nèi)存泄漏問題,修復(fù)。

"probably lost":你的程序看起來像是有內(nèi)存泄漏,有可能你在使用指針完成一些特定操作,因此不一定100%存在問題。

原文標(biāo)題:一個耗時4小時的內(nèi)存泄漏問題

文章出處:【微信公眾號:玩轉(zhuǎn)單片機(jī)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

責(zé)任編輯:haq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 數(shù)據(jù)
    +關(guān)注

    關(guān)注

    8

    文章

    7224

    瀏覽量

    90194
  • 服務(wù)器
    +關(guān)注

    關(guān)注

    12

    文章

    9435

    瀏覽量

    86510
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    3081

    瀏覽量

    74605

原文標(biāo)題:一個耗時4小時的內(nèi)存泄漏問題

文章出處:【微信號:mcu168,微信公眾號:硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    使用OpenVINO?進(jìn)行推理時的內(nèi)存泄漏怎么解決?

    使用 OpenVINO? 進(jìn)行推理時,內(nèi)存會隨著時間的推移而增加,并導(dǎo)致程序崩潰。
    發(fā)表于 03-06 08:29

    內(nèi)存泄漏檢測工具Sanitizer介紹

    內(nèi)存泄漏,我們經(jīng)常會遇到,如何檢測內(nèi)存泄漏,除了我們之前講過的 valgrind,還可以使用 gcc 自帶的工具 sanitizer。
    的頭像 發(fā)表于 03-01 14:52 ?208次閱讀

    服務(wù)器如何處理 HTTP 請求

    服務(wù)處理HTTP請求的過程是一個有序且復(fù)雜的流程,通常涉及多個步驟。以下是服務(wù)處理HTTP請求的具體步驟: 監(jiān)聽端口 :HTTP服務(wù)器在
    的頭像 發(fā)表于 12-30 09:37 ?258次閱讀

    AFE5809EVM GUI如何處理低頻信號?

    請教如何處理低頻信號。 對AFE5809EVM GUI進(jìn)行如下圖設(shè)置,請問是否正確。
    發(fā)表于 12-09 07:04

    虛擬內(nèi)存溢出該怎么處理 虛擬內(nèi)存在服務(wù)器中的應(yīng)用

    、虛擬內(nèi)存溢出的原因 內(nèi)存泄漏 :程序中未正確釋放的內(nèi)存會導(dǎo)致內(nèi)存泄漏,隨著時間的推移,這些
    的頭像 發(fā)表于 12-04 09:49 ?435次閱讀

    海量數(shù)據(jù)處理需要多少RAM內(nèi)存

    海量數(shù)據(jù)處理所需的RAM(隨機(jī)存取存儲器)內(nèi)存量取決于多個因素,包括數(shù)據(jù)的具體規(guī)模、處理任務(wù)的復(fù)雜性、數(shù)據(jù)庫管理系統(tǒng)的效率以及所使用軟件的優(yōu)化程度等。以下是對所需內(nèi)存量的分析: 一、
    的頭像 發(fā)表于 11-11 09:56 ?690次閱讀

    服務(wù)器cpu占用率高怎么解決

    長時間運行的計算任務(wù) 應(yīng)用程序存在內(nèi)存泄漏,導(dǎo)致CPU占用率上升 系統(tǒng)問題 操作系統(tǒng)配置不當(dāng),導(dǎo)致CPU占用率高 系統(tǒng)存在病毒或者惡意軟件,占用大量CPU資源 系統(tǒng)存在硬件故障,導(dǎo)致C
    的頭像 發(fā)表于 10-10 15:14 ?1280次閱讀

    使用tlc2274空腳要如何處理?

    使用 tlc2274 空腳要如何處理
    發(fā)表于 09-19 07:49

    請問比較器不用的引腳如何處理比較好?

    想請問一下,比較器不用的引腳如何處理比較好 前段時間看了一個國外比較老的板子,他將比較器不用引腳處理成如下, 總感覺有點怪怪的,請專家給點意見,如何處理比較好
    發(fā)表于 08-12 07:40

    如何檢測內(nèi)存泄漏

    檢測內(nèi)存泄漏是軟件開發(fā)過程中一項至關(guān)重要的任務(wù),它有助于識別和解決那些導(dǎo)致程序占用過多內(nèi)存資源,從而影響程序性能甚至導(dǎo)致程序崩潰的問題。以下將詳細(xì)闡述幾種常見的內(nèi)存
    的頭像 發(fā)表于 07-30 11:50 ?2583次閱讀

    NONOS 1.5.3/1.5.4 SSL內(nèi)存泄漏的原因?

    我已經(jīng)通過隨附的代碼驗證了當(dāng)發(fā)生 SSL 握手錯誤時,會生成內(nèi)存泄漏 此外,espconn_reconnect_callback不稱為信令ESPCONN_HANDSHAKE - TCP SSL 握手
    發(fā)表于 07-18 07:24

    使用system_show_malloc()檢查內(nèi)存泄漏遇到異常怎么解決?

    我想使用system_show_malloc()檢查內(nèi)存泄漏,但是當(dāng)我調(diào)用該函數(shù)時,我得到了致命的異常: 致命異常 28 (LoadProhibitedCause): epc1
    發(fā)表于 07-10 06:32

    ESP8266如何處理去抖動?

    有沒有辦法在智能插頭中處理去抖動鍵? 我的意思是為了節(jié)省成本,添加 debounce 代碼更好,如果在硬件方面有一些想法會更好。 有人有一些與這種去抖動相關(guān)的解決方案嗎? 或者有人曾經(jīng)應(yīng)用添加開關(guān)并測量這個ESP8266如何處理去抖動?
    發(fā)表于 07-08 08:23

    化工廠液體泄漏識別預(yù)警算法

    化工廠液體泄漏識別預(yù)警基于圖像識別算法是計算機(jī)視覺的基礎(chǔ)算法,例如VGG,GoogLeNet,ResNet等,化工廠液體泄漏識別這類算法主要是判斷圖片中目標(biāo)的種類液體泄漏識別預(yù)警自動識別監(jiān)控視頻中機(jī)械管道是否
    的頭像 發(fā)表于 07-03 08:35 ?580次閱讀
    化工廠液體<b class='flag-5'>泄漏</b>識別預(yù)警算法

    C語言內(nèi)存泄漏問題原理

    內(nèi)存泄漏問題只有在使用堆內(nèi)存的時候才會出現(xiàn),棧內(nèi)存存在內(nèi)存泄漏問題,因為棧
    發(fā)表于 03-19 11:38 ?625次閱讀
    C語言<b class='flag-5'>內(nèi)存</b><b class='flag-5'>泄漏</b>問題原理
    主站蜘蛛池模板: 视频在线观看网站免费 | 欧美性妇 | 一级特黄aaa大片 | 国模私拍在线观看 | 999久久精品国产 | 欧美中出 | 亚洲午夜大片 | 婷婷的五月| 伊人狼人在线 | 5151hh四虎国产精品 | 久青草国产免费观看 | 在线好吊色视频98gao | 午夜精品一区二区三区在线观看 | 午夜性影院 | 亚洲日本在线观看视频 | 色综合一区二区三区 | 在线播放国产一区 | 日本一区二区精品88 | 四虎影院在线观看免费 | 国色天香网在线 | www你懂的| 精品欧美激情在线看 | 青草国内精品视频在线观看 | 午夜aaaaaaaaa视频在线 | 手机在线看片福利 | 国产精品无码永久免费888 | 99r8这里精品热视频免费看 | 国产精品臀控福利在线观看 | 久久夜夜操 | 免费三级黄色 | 日本最黄 | 亚洲伊人久久综合影院2021 | 人人看人人看人做人人模 | 美女视频大全美女视频黄 | 日本在线不卡免费 | 久久男人网| 1024免费永久福利视频 | 啪啪网站免费 | 国产精品一区电影 | 国产精品香蕉成人网在线观看 | 1024手机看片国产旧版你懂的 |