內(nèi)存問(wèn)題 2025-09-28

寫程序的時(shí)候都會(huì)遇到哪些內(nèi)存問(wèn)題

內(nèi)存問(wèn)題類型 主要含義 潛在影響與常見(jiàn)場(chǎng)景
內(nèi)存泄漏 (Memory Leak) 分配的內(nèi)存未能釋放,不再使用的內(nèi)存無(wú)法回收 。 應(yīng)用程序內(nèi)存逐漸耗盡,運(yùn)行變慢,甚至異常終止 。長(zhǎng)期運(yùn)行的系統(tǒng)(如服務(wù)器、后臺(tái)服務(wù))影響更大。
內(nèi)存溢出 (Out of Memory) 程序申請(qǐng)內(nèi)存時(shí),系統(tǒng)沒(méi)有足夠的空間滿足其請(qǐng)求 。 程序運(yùn)行中斷或崩潰。常見(jiàn)于處理大量數(shù)據(jù)、內(nèi)存設(shè)置過(guò)小或內(nèi)存泄漏積累后 。
內(nèi)存越界 (Out-of-Bounds Access) 訪問(wèn)了分配時(shí)規(guī)定的內(nèi)存范圍之外的空間(如數(shù)組越界)。 數(shù)據(jù)損壞:可能破壞其他變量或關(guān)鍵數(shù)據(jù);程序崩潰:訪問(wèn)非法地址時(shí)觸發(fā);安全漏洞:可能被利用執(zhí)行惡意代碼 。
緩沖區(qū)溢出 (Buffer Overflow) 向緩沖區(qū)(如數(shù)組)寫入超過(guò)其容量的數(shù)據(jù),覆蓋了相鄰內(nèi)存 。 同內(nèi)存越界類似,但常強(qiáng)調(diào)因?qū)懭脒^(guò)多數(shù)據(jù)導(dǎo)致溢出,是安全攻擊的常見(jiàn)目標(biāo) 。
懸空指針/野指針 (Dangling Pointer/Wild Pointer) 指針指向的內(nèi)存已被釋放或未初始化 。 訪問(wèn)它們會(huì)導(dǎo)致未定義行為,如讀取到垃圾數(shù)據(jù)或程序崩潰 。
訪問(wèn)未初始化內(nèi)存 (Accessing Uninitialized Memory) 讀取了未賦初值的內(nèi)存內(nèi)容,值不確定 。 程序行為不可預(yù)測(cè),結(jié)果可能錯(cuò)誤 。
雙重釋放 (Double Free) 對(duì)同一塊動(dòng)態(tài)內(nèi)存釋放了兩次 。 可能破壞內(nèi)存管理器的數(shù)據(jù)結(jié)構(gòu),導(dǎo)致程序崩潰或潛在的安全問(wèn)題 。
內(nèi)存碎片 (Memory Fragmentation) 雖有足夠的總空閑內(nèi)存,但缺乏大的連續(xù)塊來(lái)滿足分配請(qǐng)求 。 可能導(dǎo)致內(nèi)存分配失?。词箍們?nèi)存足夠),降低內(nèi)存使用效率 。
  • 內(nèi)存泄漏 (Memory Leak):指的是程序未能釋放不再使用的內(nèi)存。就像水池有個(gè)小洞在不停漏水,可用內(nèi)存逐漸減少。積累到一定程度就可能引發(fā)內(nèi)存溢出。
    • 常發(fā)性內(nèi)存泄漏:發(fā)生內(nèi)存泄漏的代碼會(huì)被多次執(zhí)行到,每次執(zhí)行都導(dǎo)致一塊內(nèi)存泄漏 。
    • 偶發(fā)性內(nèi)存泄漏:發(fā)生內(nèi)存泄漏的代碼只有在某些特定環(huán)境或操作過(guò)程下才會(huì)發(fā)生 。
    • 一次性內(nèi)存泄漏:發(fā)生內(nèi)存泄漏的代碼只會(huì)被執(zhí)行一次,或者由于算法缺陷,導(dǎo)致總有且僅有一塊內(nèi)存發(fā)生泄漏 。
    • 隱式內(nèi)存泄漏:程序在運(yùn)行過(guò)程中不停的分配內(nèi)存,直到結(jié)束時(shí)才釋放。對(duì)于需長(zhǎng)期運(yùn)行的程序(如服務(wù)器),這可能導(dǎo)致內(nèi)存耗盡 。

我對(duì)于內(nèi)存問(wèn)題在寫代碼的應(yīng)對(duì)方式

第一個(gè)肯定是良好的編程習(xí)慣

遵循RAII原則()、使用智能指針(想要做的就是對(duì)資源的及時(shí)回收防止內(nèi)存泄漏)
注意不要棧溢出(比如說(shuō)遞歸終止條件、有棧協(xié)程分配空間的時(shí)候)、容器或數(shù)組的越界、程序向系統(tǒng)索要內(nèi)存問(wèn)題。

編譯階段

(c/c++)
ASan: 內(nèi)存錯(cuò)誤
TSan: 線程競(jìng)爭(zhēng)
UBSan: 未定義行為
LSan: 內(nèi)存泄漏

Sanitizer工具 檢測(cè)的問(wèn)題
AddressSanitizer (ASan) 內(nèi)存越界、use-after-free
UndefinedBehaviorSanitizer (UBSan) 整數(shù)溢出、除零、空指針
ThreadSanitizer (TSan) 多線程數(shù)據(jù)競(jìng)爭(zhēng)
LeakSanitizer (LSan) 內(nèi)存泄漏

使用問(wèn)題

(僅在測(cè)試階段使用)
TSan一般要單獨(dú)使用(因?yàn)榕cUBSan不兼容)
LSan以及集成到ASan中了

g++ -o my_program my_program.cpp -g -fsanitize=<sanitizer_name>
LSan
g++ -o my_program my_program.cpp -g -fsanitize=leak
ASan
g++ -o my_program my_program.cpp -g -fsanitize=address
UndefinedBehaviorSanitizer (UBSan)
g++ -o my_program my_program.cpp -g -fsanitize=undefined
TSan
g++ -o my_program my_program.cpp -g -fsanitize=thread

也可以集成使用,通常是將ASan與UBSan集成

g++ -o my_program my_program.cpp -g -fsanitize=address,undefined
//
g++ -O1 -g -fno-omit-frame-pointer -fsanitize=address,undefined -o my_program my_program.cpp
# 注意:LeakSanitizer (leak) 不需要顯式寫出,因?yàn)樗寻?address 中。

放到cmake中

cmake_minimum_required(VERSION 3.10)
project(MyProject)

# 創(chuàng)建可執(zhí)行文件
add_executable(my_program my_program.cpp)

# 為特定目標(biāo)設(shè)置編譯和鏈接選項(xiàng)
target_compile_options(my_program PRIVATE 
    -O1 
    -g 
    -fno-omit-frame-pointer 
    -fsanitize=address,undefined
)

# Sanitizer 通常也需要鏈接相應(yīng)的運(yùn)行時(shí)庫(kù)
target_link_libraries(my_program PRIVATE 
    -fsanitize=address,undefined
)

Valgrind

(c/c++ linux)

wait....

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容