VS2015编写C++如何查找内存泄漏漏怎么显示出来文件名和行号

vs2005 编译 下面这段代码出现内存泄漏,为什么在输出窗口看不到内存泄漏的文件名和行号呢? 请指点 - VC/MFC当前位置:& &&&vs2005 编译 下面这段代码出现内存泄漏,为什么在输vs2005 编译 下面这段代码出现内存泄漏,为什么在输出窗口看不到内存泄漏的文件名和行号呢? 请指点&&网友分享于:&&浏览:65次vs2005 编译 下面这段代码出现内存泄漏,为什么在输出窗口看不到内存泄漏的文件名和行号呢? 请大虾指点#define _CRTDBG_MAP_ALLOC#include &stdafx.h&#include &iostream&#include &stdlib.h&#include &crtdbg.h&int main(){ &
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); &
std::string* str = new std::string(&car mashins&); &
return 0;}I know that there is memory leaks here and VS2005 show me this:Detected memory leaks!Dumping objects -&{117} normal block at 0x bytes long.Data: & car mash& 00 00 00 00 CD CD CD CD 63 61 72 20 6D 61 73 68Object dump complete.------解决方案--------------------
因为VS得功能没那么强大
12345678910
12345678910
12345678910 上一篇:下一篇:文章评论相关解决方案 12345678910 Copyright & &&版权所有新手园地& & & 硬件问题Linux系统管理Linux网络问题Linux环境编程Linux桌面系统国产LinuxBSD& & & BSD文档中心AIX& & & 新手入门& & & AIX文档中心& & & 资源下载& & & Power高级应用& & & IBM存储AS400Solaris& & & Solaris文档中心HP-UX& & & HP文档中心SCO UNIX& & & SCO文档中心互操作专区IRIXTru64 UNIXMac OS X门户网站运维集群和高可用服务器应用监控和防护虚拟化技术架构设计行业应用和管理服务器及硬件技术& & & 服务器资源下载云计算& & & 云计算文档中心& & & 云计算业界& & & 云计算资源下载存储备份& & & 存储文档中心& & & 存储业界& & & 存储资源下载& & & Symantec技术交流区安全技术网络技术& & & 网络技术文档中心C/C++& & & GUI编程& & & Functional编程内核源码& & & 内核问题移动开发& & & 移动开发技术资料ShellPerlJava& & & Java文档中心PHP& & & php文档中心Python& & & Python文档中心RubyCPU与编译器嵌入式开发驱动开发Web开发VoIP开发技术MySQL& & & MySQL文档中心SybaseOraclePostgreSQLDB2Informix数据仓库与数据挖掘NoSQL技术IT业界新闻与评论IT职业生涯& & & 猎头招聘IT图书与评论& & & CU技术图书大系& & & Linux书友会二手交易下载共享Linux文档专区IT培训与认证& & & 培训交流& & & 认证培训清茶斋投资理财运动地带快乐数码摄影& & & 摄影器材& & & 摄影比赛专区IT爱车族旅游天下站务交流版主会议室博客SNS站务交流区CU活动专区& & & Power活动专区& & & 拍卖交流区频道交流区
小富即安, 积分 4181, 距离下一级还需 819 积分
论坛徽章:2
系统编程中一个重要的方面就是有效地处理与内存相关的问题。你的工作越接近系统,你就需要面对越多的内存问题。有时这些问题非常琐碎,而更多时候它会演变成一个调试内存问题的恶梦。所以,在实践中会用到很多工具来调试内存问题。
在本文中,我们将讨论最流行的开源内存管理框架 VALGRIND。
摘自 Valgrind.org:
Valgrind是用于构建动态分析工具的探测框架。它包括一个工具集,每个工具执行某种类型的调试、分析或类似的任务,以帮助完善你的程序。Valgrind的架构是模块化的,所以可以容易地创建新的工具而又不会扰乱现有的结构。
许多有用的工具被作为标准而提供。
Memcheck是一个内存错误检测器。它有助于使你的程序,尤其是那些用C和C++写的程序,更加准确。
Cachegrind是一个缓存和分支预测分析器。它有助于使你的程序运行更快。
Callgrind是一个调用图缓存生成分析器。它与Cachegrind的功能有重叠,但也收集Cachegrind不收集的一些信息。
Helgrind是一个线程错误检测器。它有助于使你的多线程程序更加准确。
DRD也是一个线程错误检测器。它和Helgrind相似,但使用不同的分析技术,所以可能找到不同的问题。
Massif是一个堆分析器。它有助于使你的程序使用更少的内存。
DHAT是另一种不同的堆分析器。它有助于理解块的生命期、块的使用和布局的低效等问题。
SGcheck是一个实验工具,用来检测堆和全局数组的溢出。它的功能和Memcheck互补:SGcheck找到Memcheck无法找到的问题,反之亦然。
BBV是个实验性质的SimPoint基本块矢量生成器。它对于进行计算机架构的研究和开发很有用处。
也有一些对大多数用户没有用的小工具:Lackey是演示仪器基础的示例工具;Nulgrind是一个最小化的Valgrind工具,不做分析或者操作,仅用于测试目的。
在这篇文章我们将关注“memcheck”工具。
使用 Valgrind Memcheck
memcheck工具的使用方式如下:
valgrind --tool=memcheck ./a.out
从上面的命令可以清楚的看到, 主要的命令是valgrind,而我们想使用的工具是通过'-tool'选项来指定的. 上面的‘a.out’指的是我们想使用memcheck运行的可执行文件.
该工具可以检测下列与内存相关的问题 :
未释放内存的使用
对释放后内存的读/写
对已分配内存块尾部的读/写
不匹配的使用malloc/new/new[] 和 free/delete/delete[]
重复释放内存
注意: 上面列出的并不很全面,但却包含了能被该工具检测到的很多普遍的问题.
让我们一个一个地对上面的场景进行讨论:
注意: 下面讨论的所有测试代码都应该使用gcc并且加上-g选项(用来在memcheck的输出中生成行号)进行编译. 就想我们之前讨论过的 C程序被编译成可执行文件, 它需要经历四个不同的阶段.
1. 使用未初始化的内存
#include &stdio.h&
#include &stdlib.h&
int main(void)
& & char *p;
& & char c = *p;
& & printf(&\n [%c]\n&,c);
& & return 0;
在上面的代码中,我们尝试使用未初始化的指针 ‘p’.
让我们运行Memcheck来看下结果.
$ valgrind --tool=memcheck ./val
==2862== Memcheck, a memory error detector
==2862== Copyright (C) , and GNU GPL'd, by Julian Seward et al.
==2862== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==2862== Command: ./val
==2862== Use of uninitialised value of size 8
==2862==& & at 0x400530: main (valgrind.c:8)
==2862== HEAP SUMMARY:
==2862==& &&&in use at exit: 0 bytes in 0 blocks
==2862==& &total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==2862== All heap blocks were freed -- no leaks are possible
==2862== For counts of detected and suppressed errors, rerun with: -v
==2862== Use --track-origins=yes to see where uninitialized values come from
==2862== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
从上面的输出可以看到,Valgrind检测到了未初始化的变量,然后给出了警告(上面加粗的几行(译者注:貌似上面没有加粗的)).
2. 在内存被释放后进行读/写
#include &stdio.h&
#include &stdlib.h&
int main(void)
& & char *p = malloc(1);
& & *p = 'a';
& & char c = *p;
& & printf(&\n [%c]\n&,c);
& & free(p);
& & c = *p;
& & return 0;
上面的代码中,我们有一个释放了内存的指针 ‘p’ 然后我们又尝试利用指针获取值.
让我们运行memcheck来看一下Valgrind对这种情况是如何反应的.
$ valgrind --tool=memcheck ./val
==2849== Memcheck, a memory error detector
==2849== Copyright (C) , and GNU GPL'd, by Julian Seward et al.
==2849== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==2849== Command: ./val
==2849== Invalid read of size 1
==2849==& & at 0x400603: main (valgrind.c:30)
==2849==&&Address 0x51b0040 is 0 bytes inside a block of size 1 free'd
==2849==& & at 0x4C270BD: free (vg_replace_malloc.c:366)
==2849==& & by 0x4005FE: main (valgrind.c:29)
==2849== HEAP SUMMARY:
==2849==& &&&in use at exit: 0 bytes in 0 blocks
==2849==& &total heap usage: 1 allocs, 1 frees, 1 bytes allocated
==2849== All heap blocks were freed -- no leaks are possible
==2849== For counts of detected and suppressed errors, rerun with: -v
==2849== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
从上面的输出内容可以看到,Valgrind检测到了无效的读取操作然后输出了警告 ‘Invalid read of size 1′.
另注,使用gdb来调试c程序.
3. 从已分配内存块的尾部进行读/写
#include &stdio.h&
#include &stdlib.h&
int main(void)
& & char *p = malloc(1);
& & *p = 'a';
& & char c = *(p+1);
& & printf(&\n [%c]\n&,c);
& & free(p);
& & return 0;
在上面的代码中,我们已经为‘p’分配了一个字节的内存,但我们在将值读取到 ‘c’中的时候使用的是地址p+1.
现在我们使用Valgrind运行上面的代码 :
$ valgrind --tool=memcheck ./val
==2835== Memcheck, a memory error detector
==2835== Copyright (C) , and GNU GPL'd, by Julian Seward et al.
==2835== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==2835== Command: ./val
==2835== Invalid read of size 1
==2835==& & at 0x4005D9: main (valgrind.c:25)
==2835==&&Address 0x51b0041 is 0 bytes after a block of size 1 alloc'd
==2835==& & at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==2835==& & by 0x4005C5: main (valgrind.c:22)
==2835== HEAP SUMMARY:
==2835==& &&&in use at exit: 0 bytes in 0 blocks
==2835==& &total heap usage: 1 allocs, 1 frees, 1 bytes allocated
==2835== All heap blocks were freed -- no leaks are possible
==2835== For counts of detected and suppressed errors, rerun with: -v
==2835== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
同样,该工具在这种情况下也检测到了无效的读取操作.
4. 内存泄露
#include &stdio.h&
#include &stdlib.h&
int main(void)
& & char *p = malloc(1);
& & *p = 'a';
& & char c = *p;
& & printf(&\n [%c]\n&,c);
& & return 0;
在这次的代码中, 我们申请了一个字节但是没有将它释放.现在让我们运行Valgrind看看会发生什么:
$ valgrind --tool=memcheck --leak-check=full ./val
==2888== Memcheck, a memory error detector
==2888== Copyright (C) , and GNU GPL'd, by Julian Seward et al.
==2888== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==2888== Command: ./val
==2888== HEAP SUMMARY:
==2888==& &&&in use at exit: 1 bytes in 1 blocks
==2888==& &total heap usage: 1 allocs, 0 frees, 1 bytes allocated
==2888== 1 bytes in 1 blocks are definitely lost in loss record 1 of 1
==2888==& & at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==2888==& & by 0x400575: main (valgrind.c:6)
==2888== LEAK SUMMARY:
==2888==& & definitely lost: 1 bytes in 1 blocks
==2888==& & indirectly lost: 0 bytes in 0 blocks
==2888==& && &possibly lost: 0 bytes in 0 blocks
==2888==& & still reachable: 0 bytes in 0 blocks
==2888==& && && &suppressed: 0 bytes in 0 blocks
==2888== For counts of detected and suppressed errors, rerun with: -v
==2888== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
输出行(上面加粗的部分)显示,该工具能够检测到内存的泄露.
注意: 在这里我们增加了一个选项‘–leak-check=full’来得到内存泄露的详细细节.
5. 不匹配地使用malloc/new/new[] 和 free/delete/delete[]
#include &stdio.h&
#include &stdlib.h&
#include&iostream&
int main(void)
& & char *p = (char*)malloc(1);
& & *p = 'a';
& & char c = *p;
& & printf(&\n [%c]\n&,c);
& & return 0;
上面的代码中,我们使用了malloc()来分配内存,但是使用了delete操作符来删除内存.
注意 : 使用g++来编译上面的代码,因为delete操作符是在C++中引进的,而要编译C++需要使用g++.
让我们运行来看一下 :
$ valgrind --tool=memcheck --leak-check=full ./val
==2972== Memcheck, a memory error detector
==2972== Copyright (C) , and GNU GPL'd, by Julian Seward et al.
==2972== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==2972== Command: ./val
==2972== Mismatched free() / delete / delete []
==2972==& & at 0x4C26DCF: operator delete(void*) (vg_replace_malloc.c:387)
==2972==& & by 0x40080B: main (valgrind.c:13)
==2972==&&Address 0x595e040 is 0 bytes inside a block of size 1 alloc'd
==2972==& & at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==2972==& & by 0x4007D5: main (valgrind.c:7)
==2972== HEAP SUMMARY:
==2972==& &&&in use at exit: 0 bytes in 0 blocks
==2972==& &total heap usage: 1 allocs, 1 frees, 1 bytes allocated
==2972== All heap blocks were freed -- no leaks are possible
==2972== For counts of detected and suppressed errors, rerun with: -v
==2972== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
从上面的输出可以看到 (加粗的行), Valgrind清楚的说明了‘不匹配的使用了free() / delete / delete []‘
你可以尝试在测试代码中使用'new'和'free'进行组合来看看Valgrind给出的结果是什么.
6. 两次释放内存
#include &stdio.h&
#include &stdlib.h&
int main(void)
& & char *p = (char*)malloc(1);
& & *p = 'a';
& & char c = *p;
& & printf(&\n [%c]\n&,c);
& & free(p);
& & free(p);
& & return 0;
在上面的代码中, 我们两次释放了'p'指向的内存. 现在让我们运行memcheck :
$ valgrind --tool=memcheck --leak-check=full ./val
==3167== Memcheck, a memory error detector
==3167== Copyright (C) , and GNU GPL'd, by Julian Seward et al.
==3167== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==3167== Command: ./val
==3167== Invalid free() / delete / delete[]
==3167==& & at 0x4C270BD: free (vg_replace_malloc.c:366)
==3167==& & by 0x40060A: main (valgrind.c:12)
==3167==&&Address 0x51b0040 is 0 bytes inside a block of size 1 free'd
==3167==& & at 0x4C270BD: free (vg_replace_malloc.c:366)
==3167==& & by 0x4005FE: main (valgrind.c:11)
==3167== HEAP SUMMARY:
==3167==& &&&in use at exit: 0 bytes in 0 blocks
==3167==& &total heap usage: 1 allocs, 2 frees, 1 bytes allocated
==3167== All heap blocks were freed -- no leaks are possible
==3167== For counts of detected and suppressed errors, rerun with: -v
==3167== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
从上面的输出可以看到(加粗的行), 该功能检测到我们对同一个指针调用了两次释放内存操作.
在本文中,我们把注意力放在了内存管理框架Valgrind,然后使用memcheck(Valgrind框架提供的)工具来了解它是如何降低需要经常操作内存的程序员的负担的. 该工具能够检测到很多手动检测不到的与内存相关的问题
&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp
小富即安, 积分 3681, 距离下一级还需 1319 积分
论坛徽章:5
不错 感谢分享
家境小康, 积分 1548, 距离下一级还需 452 积分
论坛徽章:0
补充一句,gcc4.8+的版本自带了内存泄露检测。有统计表示,效率比valgrind高20倍。
丰衣足食, 积分 978, 距离下一级还需 22 积分
论坛徽章:6
liuweni 发表于
补充一句,gcc4.8+的版本自带了内存泄露检测。有统计表示,效率比valgrind高20倍。
有资料吗,给个链接看看。
家境小康, 积分 1548, 距离下一级还需 452 积分
论坛徽章:0
AddressSanitizer , a fast memory error detector, has been added and can be enabled via -fsanitize=address. Memory access instructions will be instrumented to detect heap-, stack-, and global-buffer overflow as well as use-after-free bugs. To get nicer stacktraces, use -fno-omit-frame-pointer. The AddressSanitizer is available on IA-32/x86-64/x32/PowerPC/PowerPC64 GNU/Linux and on x86-64 Darwin.
论坛徽章:6
富甲一方, 积分 45083, 距离下一级还需 4917 积分
论坛徽章:205
很实用,lz终于接地气了
家境小康, 积分 1397, 距离下一级还需 603 积分
论坛徽章:1
本帖最后由 fly3ds 于
15:33 编辑
看似很好,&&其实是没用的东西.& &这几段小程序不用工具检查看一眼就知道了,&&等问题复杂到看不出来,&&用这玩意肯定也找不出什么东西来.
我这么说是有理由的,&&假如真的有用,&&现在的C/C++项目那么多,&&Linux GCC 各种大大小小开源不开源的项目. 为啥不随便找一个知名项目用这玩意来查查报bug呢?
我看这东西不但不会减少程序员的负担,& &反而会增加程序员的负担,& &因为出了这么个东西,&&就会有不明真相的人关注,& &然后试用,& &找资料, 求助; 绕了一大圈,&&终于摸透了,&&得出结论了,&&没用 !& & 时间也浪费掉了.& &而别人,&&仔细的检查自己的程序, 一个函数一个函数慢慢来,&&每个函数都测试过几遍,& &甚至专门做了单元测试,& &已经完成任务在喝茶了.  &&
白手起家, 积分 9, 距离下一级还需 191 积分
论坛徽章:1
挺好的,感谢楼主和楼上各位的分享{:2_171:}
白手起家, 积分 50, 距离下一级还需 150 积分
论坛徽章:0
valgrind是非常有用的, 程序越大, 越复杂, 越能显出它的用处, 程序小片断可以用人肉办法检查, 多了人工方法就不行了, 到那时候你是没功夫喝茶的.&&一个工具对付不同规模的输入, 是否能一致地有效有用, 取决于它的工作原理, 比如一些static checker/lint工具, 对于简单的C/C++代码还有用, 对于复杂的代码, 比如含有复杂的宏, 使用了高级语言特性如boost之于STL, 这些工具可能就处理不了了.
但valgrind对于内存的检查, 却是基于对下层内存分配器的instrument或截获来实现的, 正因为这一点, 它支持C也就自然支持C++, 不多费一分钟功夫, 因为它是运行时检测工具, 不在语言这个层面上工作. 对于内存越界的检查, 典型的做法是, 让内存分配器分配出要求的内存后, 让请求的内存的下一个字节, 位于一个不同的page上, 而这个page的访问权限, 设置为不可读写, 这样, 对给定内存块哪怕是越界读取一个字节, 也会同步地马上触发访问异常, 因为CPU的内存管理单元会在硬件层面触发异常, OS的异常处理机制处理这个异常, 再把这个异常转交给应用程序处理, 应用程序若不处理, OS再进行默认处理, 据我了解, valgrind的windows下的application verifier 对内存越界的实现都是基于这个原理.
我对valgrind的有限经验表明每一次使用它都能找出真正的问题, 而不是误报. 无关语言, 无关release/debug, 也无关编译时有没有生成调试信息. 它都能正常工作.
必需说明, 我对valgrind使用有限, 了解并不全面.VS2015编写C++查找内存泄漏怎么显示出来文件名和行号?新手求解。 - 知乎4被浏览204分享邀请回答0添加评论分享收藏感谢收起0添加评论分享收藏感谢收起12535人阅读
C++(118)
windows(96)
在Visual&C++中检测和隔离内存泄漏
具有动态的分配和释放内存的能力是C/C++程序语言的重要特色之一。VisualC++&debugger和CRT库提供了一系列有效的检测和鉴定内存泄漏的工具。
设置内存泄漏检测
  检测内存泄漏的基本工具是调试器和CRT调试堆函数。为了使用调试堆函数,在你的程序中你必须含有下面的说明:
#define&_CRTDBG_MAP_ALLOC
#include&stdlib.h&
#include&crtdbg.h&
必须保证上面声明的顺序,如果改变了顺序,可能不能正常工作。&crtdbg.h&的_malloc_dbg和_free_dbg将取代标准的malloc和free函数出现在DEBUG版中,它可以跟踪内存的分配和释放。但是这只会在DEBUG版本中发生(当#define&_DEBUG的时候),而Release版本仍使用标准的malloc和free功能。
#define&_CRTDBG_MAP_ALLOC表示使用CRT堆函数的相应的DEBUG版本。这个定义不是必须的,但是没有它,内存泄漏报告含有的只是没有什么用处的信息。
  一旦你已经添加了刚才的声明,你就能够通过在程序中加入下面的代码来报告内存泄漏信息:
_CrtDumpMemoryLeaks();
当在DEBUG模式下运行程序时,在Output窗口的Debug标签处_CrtDumpMemoryLeaks会显示内存泄漏的信息,例如:
Detected&memory&leaks!
Dumping&objects&-&
C:\PROGRAM&FILES\VISUAL&STUDIO\MyProjects\leaktest\leaktest.cpp(20)&:&{18}&normal&block&at&0x&bytes&long.
Data:&&&&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&
Object&dump&complete.
如果没有#define&_CRTDBG_MAP_ALLOC,内存泄漏报告就会像下面这样:
Detected&memory&leaks!
Dumping&objects&-&
{18}&normal&block&at&0x&bytes&long.
Data:&&&&&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&
Object&dump&complete.
  由此可见,定义_CRTDBG_MAP_ALLOC时,_CrtDumpMemoryLeaks可以提供更多的有用信息。
  如果没有定义_CRTDBG_MAP_ALLOC,那么内存泄漏报告如下显示:
   内存分配数值(花括号内)
   模块的类型(normal、client或者CRT)
   以十六进制格式定位的内存
   以字节计模块的大小
   第一个十六字节的内容(也可以用十六进制)
  如果定义了_CRTDBG_MAP_ALLOC,报告的内容还包括出现分配所泄漏内存的文件。在文件名之后括号内的数字是文件内的行数值。
  此时双击包含行数值和文件名的输出行,&或者选择输出行并按F4:
C:\PROGRAM&FILES\VISUAL&STUDIO\MyProjects\leaktest\leaktest.cpp(20)&:&{18}&normal&block&at&0x&bytes&long.
  编辑窗口将会跳到文件中分配所泄漏内存的那一行代码,leaktest.cpp中的行号为20的那一行。
  &使用_CrtSetDbgFlag
  如果你的程序只在一个地方退出,那么在选择调用_CrtDumpMemoryLeaks的位置是非常容易的。但是,如果你的程序可能会在程序多处位置退出该怎么办?如果不希望在每一个可能的出口处调用_CrtDumpMemoryLeaks,那么你可以在你的程序开始处包含下面的调用:
_CrtSetDbgFlag(&_CRTDBG_ALLOC_MEM_DF&|&_CRTDBG_LEAK_CHECK_DF);
  当程序退出时,将会自动地调用_CrtDumpMemoryLeaks(必须设置_CRTDBG_ALLOC_MEM_DF和&_CRTDBG_LEAK_CHECK_DF)。
  翻译内存模块的类型
  内存泄漏报告中把每一块泄漏的内存分为普通块、客户块和CRT块。事实上,你只需要留心普通块和客户块类型。
  普通块(normal&block):是由你的程序分配的内存。
  客户块(client&block):是一种特殊的内存块,它是由MFC使用的一个对象,程序退出时,该对象的析构函数没有被调用。MFC&new操作符可以用来创建普通块和客户块。
  CRT块(CRT&block):是由C&RunTime&Library供自己使用而分配的内存块。CRT库自己来管理这些内存的分配与释放,通常你不会在内存泄漏报告中发现有CRT内存泄漏,除非程序发生了严重的错误(例如CRT库崩溃)。
  下面这两种类型的内存块不会出现在内存泄漏报告中:
   空闲块(free&block):已经被释放(free)的内存块。
   忽略块(Ignore&block):是程序员显式声明过不要在内存泄漏报告中出现的内存块。
设置CRT报告样式
  通常_CrtDumpMemoryLeaks()会dump内存泄漏的信息到output窗口的Debug栏位。你可以使用_CrtSetReportMode()来重新设置输出到另一个位置。关于更详细的如何使用_CrtSetReportMode()说明,请查看MSDN。
  &在内存分配数目处设置一个断点
  在内存泄漏报告中的文件名和行号可告诉分配泄漏的内存的代码位置,但是光是有这些信息对于完整了解泄漏原因,有时候还是不够的。因为一个程序在运行时,一段分配分配内存的代码将会被调用很多次,但可能是某次调用后没有释放内存而导致了泄漏内存。为了确定是那些内存没有被释放,你必须不仅要知道泄漏的内存在那里被分配,还要知道泄漏产生的条件。对你来说,有帮助的信息就是内存分配号——在文件名和行号之后的花括号对中出现的数值。
  例如,在下面的输出信息中,&18&是内存分配号,意思是泄漏的内存是你程序中分配的第十八个内存块:
Detected&memory&leaks!
Dumping&objects&-&
C:\PROGRAM&FILES\VISUAL&STUDIO\MyProjects\leaktest\leaktest.cpp(20)&:&{18}&normal&block&at&
0x&bytes&long.
Data:&&&&&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&CD&
Object&dump&complete.
CRT库为在程序运行期间分配的所有内存模块计数,包括CRT自己分配的内存或者诸如MFC等分配的其它模块。因此带有分配号n的一个对象是在你的程序中分配的第n个对象,但不代表是由那段代码分配的第n个对象(在大部分情况下,它都不会是。)
  这样的话,你可以利用分配号在内存分配的地方设置一个断点。为了设置这样一个端点,你可以在你的程序开始处,设置一个位置断点。当你的程序在那一点break时,你就能够从QuickWatch对话框或者Watch窗口设置这样一个位置断点。
  例如,在Watch窗口中,在Name栏键入下面的表达式:
_crtBreakAlloc
如果你正在用CRT库dynamic-link&library&(DLL)的多线程版本,你必须含有上下文操作符,像这样:&
{,,msvcrtd.dll}_crtBreakAlloc
现在按下RETURN键,调试器找到该值并把结果放置在value栏。如果你在内存分配过程中还没有设置任何内存分配断点,那么这个值是-1。用你想要去中断的内存分配的分配数值来,取代value表中的值——例如,18。
  当设置完内存分配断点之后,继续调试。这时,运行程序时一定要小心,要保证内存块分配的顺序不会改变。当你的程序在内存分配点中断的时候,你就能够查看Call&Stack窗口和其他的DEBUG信息来分析泄漏原因了。你仍然可以继续从那一点执行程序,以至于了解到底发生了什么,同时确定为什么内存没有被释放(设置一个内存分配断点是很有帮助的)。
  虽然在调试器中设置内存分配断点通常更容易,但是如果你喜欢的话,你也可以在你的代码中设置它们。为了在你的代码中设置一个内存分配断点,可以增加这样一行(对于第十八个内存分配):
_crtBreakAlloc&=&18;
你还有可以使用有相同效果的_CrtSetBreakAlloc函数:
_CrtSetBreakAlloc(18);
比较内存状态
  定位内存泄漏的另一个方法就是在关键点对应用程序的内存状态做快照。CRT库提供了一个结构类型_CrtMemState。你可以用它来存储内存状态的一个快照:
_CrtMemState&s1,&s2,&s3;
为了在特定点对内存状态进行快照,可以传递一个_CrtMemState结构到he&_CrtMemCheckpoint函数。此函数用当时内存状态的一个快照来填充此结构:&
_CrtMemCheckpoint(&&s1&);
你可以通过传递此结构到_CrtMemDumpStatistics函数来dump&_CrtMemState结构的任意点的内容:&
_CrtMemDumpStatistics(&&s1&);
此函数打印出类似于下面这样的一堆内存分配信息:
0&bytes&in&0&Free&Blocks.
0&bytes&in&0&Normal&Blocks.
3071&bytes&in&16&CRT&Blocks.
0&bytes&in&0&Ignore&Blocks.
0&bytes&in&0&Client&Blocks.
Largest&number&used:&3071&bytes.
Total&allocations:&3764&bytes.
为了确定一个内存泄漏是否在一节代码中出现,你可以在此节前和此节后对内存状态作快照,然后用_CrtMemDifference比较两种状态:&
_CrtMemCheckpoint(&&s1&);
//&memory&allocations&take&place&here
_CrtMemCheckpoint(&&s2&);
if&(&_CrtMemDifference(&&s3,&&s1,&&s2)&)&
_CrtMemDumpStatistics(&&s3&);
_CrtDumpMemoryLeaks();
  从名字上可以知道,_CrtMemDifference用来比较两个内存状态(最后面的那两个参数),并返回状态差异的结果(第一个参数)。在你的函数开始和结尾处的_CrtMemCheckpoint调用和使有_CrtMemDifference来比较结果为检测内存泄漏提供了另一种方法。如果检测到一个泄漏,那么可以使用_CrtMemCheckpoint调用来分割你的程序,并使用binary&search&technique来定位.
From:http://bbs.csdn.net/topics/
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:410010次
积分:4673
积分:4673
排名:第6103名
原创:38篇
转载:155篇
评论:37条
(1)(1)(3)(3)(4)(1)(1)(2)(1)(2)(1)(3)(1)(4)(1)(3)(2)(2)(1)(1)(2)(3)(3)(1)(7)(3)(3)(7)(3)(4)(1)(2)(1)(9)(5)(1)(2)(6)(1)(1)(1)(1)(6)(6)(2)(7)(7)(8)(1)(3)(3)(7)(2)(4)(2)(20)(5)(6)(1)}

我要回帖

更多关于 linux 模糊查找文件名 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信