本菜鸡遇到一个简单而有趣的bug竟然困扰了挺久。记录一下,绝不再犯!
背景: 做个Demo,需要统计编码完每帧图像的相关信息,比如码率、质量、编码参数等信息。
内容:
- 因为参数分布在不同的文件和函数里面,编码帧数不确定,所以定义了一个全局变量(指针)。
int* InfoRecord = NULL;
- 在根据YUV文件大小、宽高、采样信息确认了编码总帧数之后,给指针动态分配内存。
InfoRecord = new int[totalFrames / gopLenth + totalFrames % gopLenth > 0 ? 1 : 0];
- 调用编码器编码,调用解码器解码,根据 frameIdx 填写到对应的 InfoRecord 里面。
- 信息输出结束,释放内存。
delete[] InfoRecord;
InfoRecord = NULL;
delete InfoRecord;
问题出现!release没问题,debug时有时无地进行报错,修改编码参数就会影响报错的频率!
就这个问题,我一脸懵逼??? 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!!!
结果又是下图:
???????临时变量指针都不能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遍!