new完不能delete?菜雞記一個有趣的簡單BUG,絕不再犯!

本菜雞遇到一個簡單而有趣的bug竟然困擾了挺久。記錄一下,絕不再犯!

背景: 做個Demo,需要統計編碼完每幀圖像的相關信息,比如碼率、質量、編碼參數等信息。

內容

  1. 因爲參數分佈在不同的文件和函數裏面,編碼幀數不確定,所以定義了一個全局變量(指針)。
int* InfoRecord = NULL;
  1. 在根據YUV文件大小、寬高、採樣信息確認了編碼總幀數之後,給指針動態分配內存。
InfoRecord = new int[totalFrames / gopLenth + totalFrames % gopLenth > 0 ? 1 : 0];
  1. 調用編碼器編碼,調用解碼器解碼,根據 frameIdx 填寫到對應的 InfoRecord 裏面。
  2. 信息輸出結束,釋放內存。
delete[] InfoRecord;
InfoRecord = NULL;
delete InfoRecord;

問題出現!release沒問題,debug時有時無地進行報錯,修改編碼參數就會影響報錯的頻率!
bug

就這個問題,我一臉懵逼??? new了之後竟然不能delete!!!

  • 我一開始認爲 “我定義的全局指針在全局變量區,動態分配的內存在堆區,難道因爲牽扯了全局變量區,這堆區的內存不能讓我來釋放???系統要幫我管理???

  • 於是用VS debug 查看內存,結果是我想得太簡單了,在我令 “InfoRecord = NULL; ”之後,指針分配的內存仍然沒有被釋放,new完不delete果然內存泄漏!!!

在這裏插入圖片描述

  • 咋辦呢 ? 我問了旁邊實習的正統計算機本碩的同學,人家說:“臥槽,還有這種事?我也沒見過。"
  • 但是,他給我個好解決方法:“你認爲是牽扯了全局變量區所以不能自己釋放!我覺得有道理!那你按照下面這種寫法不就好了”。

① 依舊定義那個全局變量(指針)。

int* InfoRecord = NULL;

② 不要直接對着 InfoRecord 分配內存,先弄個局部變量指針分配內存,再淺拷貝,再釋放這個局部變量指針!

int InfoRecordTmp = new int[totalFrames / gopLenth + totalFrames % gopLenth > 0 ? 1 : 0];
int InfoRecord =InfoRecordTmp;

③ 之後再釋放內存。

delete[] InfoRecordTmp;
InfoRecordTmp = NULL;
delete InfoRecordTmp;

......

delete[] InfoRecord;
InfoRecord = NULL;
delete InfoRecord;

有理啊! 牛掰!
開心解決了這個BUG!!!
結果又是下圖:
bug

???????臨時變量指針都不能delete???????
??????????你是魔鬼嗎 ??????????
??????程序員生涯還沒開始就結束了??????

後來,我在百度、google、csdn上搜索各種“全局變量指針” “new完不能delete”等關鍵詞,都沒有能幫我解決的答案。
還去問了實驗室同學,最後我竟然認爲是超出能力範圍的內存管理問題。

在這裏插入圖片描述
在這裏插入圖片描述
費時費力仔細排查後發現,竟然是=====================》!!!!!!劃重點!!!!!!


本菜雞忽視了運算符順序導致new操作時大小出錯了!

錯誤:

InfoRecord = new int[totalFrames / gopLenth + totalFrames % gopLenth > 0 ? 1 : 0];

三目運算符 ? : 優先級比 + 低,new的大小出錯,導致後面釋放不了!就是少了一個括號的問題!

改成:

InfoRecord = new int[totalFrames / gopLenth + (totalFrames % gopLenth > 0 ? 1 : 0)];

菜雞啊!C++運算符優先級這種最基礎、最基礎的問題都弄錯了,還在那裏亂扯一通堆棧、全局變量區啥的玩意,真是基礎太差!下表罰抄10遍!

C++運算符優先級

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章