VC++ 堆内存溢出的检测
关于内存泄漏这样的问题,有些时候在调试程序的过程中可以解决。可是对于堆内存的使用情况,就是供程序员自由分配的内存,是一个
难以快速发现的问题,往往隐藏更深,而且在程序运行过程中表现出来的问题往往是随机的。下面来演示堆内存的情况,如下面所示:
void malloc_test()
{
test_c* test = new test_c();
char* test1 = (char*)malloc(100);
char* test2 = (char*)malloc(6);
const char* str = "this is a test";
memcpy(test2, str, strlen(str));
}
在代码中,第 7 行代码将字符串 str 通过内存拷贝的方式复制给 test2。test2 分配了 6 字节,但是复制给它的字符串超过了 6 字节。也就
是说,test2 之外的内存已经被覆盖(超过了 test2 本身的分配空间,已经溢出)。无论这种代码处于编译阶段还是运行阶段,通常情况
下不会有任何提示,运行时也不会有任何问题,所以很难靠肉眼去寻找问题。
调试函数中还有一个函数 _CrtCheckMemory
,它会检查在堆栈上分配的每一块内存的完整性。如果分配的内存没有遭到破坏,则返回
true,否则会返回 false,因此我们刚好可以把它用在 ASSERT 宏中。如果 ASSERT 条件为 true,说明我们的代码没有问题;如果为
false,就表示分配的内存出现了问题,会发生中断。我们在 main 函数代码中添加以下命令来提示堆内存是否被破坏:
ASSERT(_CrtCheckMemory());
然后直接按 F5 键启动调试,执行测试程序,弹出了 Debug Assertion Failed!
。
单击 “重试” 按钮就会定位到调用 _CrtCheckMemory
的位置,表示 _CrtCheckMemory
检查失败,部分内存被破坏。
虽然检查到部分内存已经被破坏,但是程序在退出时才提示信息远远不够,我们无法了解哪些内存被破坏,查找起来并不方便。
_CrtSetDbgFlag
的参数还有一个选项:_CRTDBG_CHECK_ALWAYS_DF
,它表示每次分配内存的时候都要检查已经分配的堆内存的完整
性。所以当一块堆内存被破坏时,并不能马上发现问题,而是在下一次分配内存时才会发现已经被破坏的堆内存,从而提示错误信息。所
以,这已经非常接近破坏堆的原始位置。启用 _CRTDBG_CHECK_ALWAYS_DF
选项以后,程序运行的速度会比正常运行速度慢,但是如果
能够即时发现问题,尤其是在开发阶段就能发现问题,这当然是值得的。测试代码如下所示:
void malloc_test()
{
test_c* test = new test_c();
char* test1 = (char*)malloc(100);
char* test2 = (char*)malloc(6);
const char* str = "this is a test";
memcpy(test2, str, strlen(str));
char* test3 = new char[10];
delete[]test3;
}
int main()
{
//启用调试对管理
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF);
std::cout << "Memory leak test" << std::endl;
_CrtSetBreakAlloc(168);
malloc_test();
//new_test();
//_ASSERT(_CrtCheckMemory());
_CrtDumpMemoryLeaks(); //显示内存泄漏报告
return 0;
}
在代码中第 14 行代码调用 _CrtSetDbgFlag
时添加了 _CRTDBG_CHECK_ALWAYS_DF
选项,以便每次分配内存时都检查堆内存的完整
性。在代码的第 33 行,我们对 test2 进行了覆盖操作,然后对 test3 进行内存分配。我们期望程序在分配 test3 时提示错误,并且能够发
生中断。编译程序并按 F5 键启动调试,会弹出错误提示对话框。
此时单击 “重试” 按钮,定位至出错位置。
可以发现,程序是在分配内存时发生中断,说明在这之前破坏了某个堆内存。切换栈帧至分配内存的代码处,即 malloc_test 的 8 行代码
处。
可以发现正在执行分配内存的操作,说明前面的某个操作导致了对某个堆内存的破坏。通过检查代码可以发现,代码的第 7 行处破坏了
test2,从而定位至代码中的堆破坏代码。
该文章会更新,欢迎大家批评指正。文章来源:https://www.toymoban.com/news/detail-533852.html
推荐一个零声学院免费公开课程,个人觉得老师讲得不错,
分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:
服务器课程:C++服务器文章来源地址https://www.toymoban.com/news/detail-533852.html
到了这里,关于VC++ 堆内存溢出的检测的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!