visual studio

您所在的位置:网站首页 vs内存不足异常怎么解决 visual studio

visual studio

2024-06-26 17:06| 来源: 网络整理| 查看: 265

近期我在windows下使用visual studio开发一个h264解码验证程序,遇到了内存越界和内存泄漏问题。总结一下vs内存调试方法。

概述

windows的C 运行时库提供了广泛的调试支持。如果 VS要使用 CRT 调试库,必须以DEBUG 方式编译,并配置runtime library为/MD、/MT、/LD(configuration-> c/c++ -> code generation -> runtime library )。可参考如下文档 微软官网CRT调试文档

原理

C 运行库包含堆内存分配函数的Debug版本。 这些函数的名称与release版本相同,只是追加了“_dbg”。 以 malloc 为例,其debug版本函数名为_malloc_dbg 。 定义 _DEBUG 时,CRT 会将所有 malloc 调用映射到 _malloc_dbg。 因此,在调试时,无需使用 _malloc_dbg 代替 malloc 重写代码。它的实现在crtdbg.h,代码如下

// crtdbg.h #define free(p) _free_debug(p, NORMAL_BLOCK) #define malloc(s) _malloc_debug(s, NORMAL_BLOCK, __FILE__, __LINE__)

原理:

每次申请内存时会把当前文件名和行号以及内存一并保存到一个双端队列,当内存释放时,从双端队列中找到该节点并删除。因此在程序出口检测该队列里节点是否为空就可以判断是否有内存泄漏了。_malloc_debug在每次申请内存时,会在内存前后多申请几个byte数据,并初始化为0xFD;释放时会检查内存前后这几个字节是否被修改,如果被修改则认为是内存越界。 具体实现可参考源码debug_heap.cpp。 调用流程大致如下: _malloc_debug -> heap_alloc_dbg -> heap_alloc_dbg_internal 使用方式

1.包含头文件并定义_CRTDBG_MAP_ALLOC宏 如果不定义_CRTDBG_MAP_ALLOC宏,检查到内存泄漏时,将无法获取内存泄漏所在文件和行号

#define _CRTDBG_MAP_ALLOC #include

2.设置调试flag _crtDbgFlag 标志包含下列位域: 检查堆完整性和内存泄漏

位域默认 value描述_CRTDBG_ALLOC_MEM_DFOn打开调试分配。 当该位为 off 时,分配仍链接在一起,但它们的块类型为 _IGNORE_BLOCK。_CRTDBG_DELAY_FREE_MEM_DFOff防止实际释放内存,与模拟内存不足情况相同。 当该位为 on 时,已释放块保留在调试堆的链接列表中,但标记为 _FREE_BLOCK,并用特殊字节值填充。_CRTDBG_CHECK_ALWAYS_DFOff每次分配和释放时均调用 _CrtCheckMemory。 这将减慢执行,但可快速捕捉错误。_CRTDBG_CHECK_CRT_DFOff将标记为 _CRT_BLOCK 类型的块包括在泄漏检测和状态差异操作中。 当该位为 off 时,在这些操作期间将忽略由运行库内部使用的内存。_CRTDBG_LEAK_CHECK_DFOff在程序退出时通过调用 _CrtDumpMemoryLeaks 来执行泄漏检查。 如果应用程序未能释放其所分配的所有内存,将生成错误报告。 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); 示例 // test.cpp : Defines the entry point for the console application. // #include "stdafx.h" #ifdef _DEBUG #define _CRTDBG_MAP_ALLOC #include #endif void memory_leak() { int tmp = _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); char* p = (char*)malloc(20); } void memory_overlap() { int tmp = _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); char* p = (char*)malloc(20); p[23] = 'f'; free(p); } int main() { memory_leak(); //memory_overlap(); return 0; }

以debug方式运行结果如下: 1.内存泄漏 memory_leak函数运行结果 从结果可以得知,test.cpp文件第14行内存申请没有释放,对应代码char* p = (char*)malloc(20); 2.内存越界 内存越界函数运行结果 从crash结果看,test.cpp文件第20行申请的内存边界被修改了,发生了越界

一些调试小技巧 如果调试时在某个内存对象发生了crash,并查看该内存数据全都是0xDD,那么可以看看该内存是不是重复释放了,因为_free_debug函数在处理内存释放前会把内存memset为0xDD。如果内存数据全为0xCD,可以查下是不是内存申请了没有把数据memset为0


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3