在进行C++开发时,如果在windows平台上,使用MFC,则可以自动检测内存泄露,如果是win32或者console程序,不使用MFC,则需要自己进行处理。
下面是在总结的一些方法,均来自网上,也经历了实际检验,在此备份。
1. 利用 KDetectMemoryLeak.h来完成类似MFC重定义NEW宏的效果。可以完成泄露点的输出。
在代码的最后,采用_CrtDumpMemoryLeaks();
具体可以参见《VS2008内存泄露检测》文档,作者写的很清楚,在此谢谢。
KDetectMemoryLeak.h 源码:
#pragma once
#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__,__LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif
2. 对于无法定位到具体源代码的泄露,可以通过分析dump出来的信息来定位。
特别是在DLL库中,经常会出现这种情况。
比如:
{152} normal block at 0x01078320, 12 bytes long.
Data: 08 79 65 00 48 82 07 01 00 00 00 00
{151} normal block at 0x010782C0, 36 bytes long.
Data: CD CD CD CD CD CD CD CD 00 00 00 00 00 00 0000
{150} normal block at 0x01078248, 56 bytes long.
Data: F4 77 65 00 00 00 00 00 68 71 07 01 90 3A 0910
《软件调试》的702页介绍了堆块转储的细节,取其中的一个堆块为例:
{137} normal block at 0x01073790, 8 bytes long.
Data: <H7> 48 37 07 01 CD CD CD CD
137是堆块的分配序号,堆块的类型为普通堆块,位置为0x01073790,用户区长度为8字节。
Data后为用户数据区的前16字节,因为这个数据区只有8字节,所以即所有8字节。<H7>是这8字节的ASCII码显示(其它6字节为不可显示的ASCII码)。其中的CD CD CDCD 是CRT在分配堆块时自动填充的固定内容(《软件调试》P696)。这说明这8个字节的堆块,应用程序使用过前4个字节,后四个字节没有使用过。
对于这样的内存泄漏,有很多种办法,你首先可以试一下23.13.1节介绍的内存分配序号断点,也就是重新运行程序,在尽可能早的时候(比如入口),设置序号断点(将_crtBreakAlloc变量设置为要中断的序号,比如137),让CRT分配到指定的内存块时中断。中断下来后,可以根据栈回溯判断是哪个模块在分配内存,记录后,再退出程序,如果这个堆块仍出现在转储列表中,那么刚才那个模块便值得怀疑了。
如果你有被怀疑的模块源代码,那么可以使用23.15.3节介绍的方法让堆块转储信息中包含源程序的文件名和行号,即下面的样子:
C:\dig\dbg\author\code\chap23\MemLeak\MemLeak.cpp(22): {74} normal block at 0x00371000, 20 bytes long.
Data: CD CD CD CD CD CD CD CD CD CD CD CD CD CD CDCD
3.可以利用 vld 进行检测。
4.还可以利用 boundcheck,purify等工具进行检测。
刚将git lab从3.0升级到4.0,很多项目导入进来。打开项目的files页面,出现500 错误。
进入服务器,观察日志:/home/gitlab/gitlab/log/production.log 文件中找到错误:
Started GET "/cloudengine/package/tree/master" for 127.0.0.1 at 2013-01-07 10:41:04 +0800 Processing by TreeController#show as HTML Parameters: {"project_id"=>"cloudengine/package", "id"=>"master"} Rendered shared/_ref_switcher.html.haml (2.7ms) Rendered shared/_clone_panel.html.haml (0.9ms) Rendered tree/_head.html.haml (5.5ms) Rendered tree/_tree_item.html.haml (4.1ms) Rendered tree/_tree.html.haml (6.9ms) Rendered tree/show.html.haml within layouts/project_resource (13.2ms) Completed 500 Internal Server Error in 54ms ActionView::Template::Error (Permission denied - (/home/gitlab/gitlab/tmp/cache/assets/sprockets%2F31f4736e6c39e984d230e798c530da2020130107-1340-1xps2q7, /home/gitlab/gitlab/tm\ p/cache/assets/CB6/C90/sprockets%2F31f4736e6c39e984d230e798c530da20)): 1: %tr{ class: "tree-item #{tree_hex_class(tree_item)}" } 2: %td.tree-item-file-name 3: = tree_icon(type) 4: %strong= link_to truncate(tree_item.name, length: 40), project_tree_path(@project, tree_join(@id || @commit.id, tree_item.name)) 5: %td.tree_time_ago.cgray 6: %span.log_loading.hide app/helpers/tree_helper.rb:33:in `tree_icon' app/views/tree/_tree_item.html.haml:3:in `_app_views_tree__tree_item_html_haml___1248346142396777318_33157860' app/helpers/tree_helper.rb:21:in `block in render_tree' app/helpers/tree_helper.rb:15:in `each' app/helpers/tree_helper.rb:15:in `render_tree' app/views/tree/_tree.html.haml:34:in `_app_views_tree__tree_html_haml___1664153310566467946_59134580' app/views/tree/show.html.haml:3:in `_app_views_tree_show_html_haml__592423701844535987_55745220' app/controllers/tree_controller.rb:17:in `show'
chmod -R 777 ./tmp
重新启动,一切OK.
Description
Input
Output
Sample Input
dog ogday cat atcay pig igpay froot ootfray loops oopslay atcay ittenkay oopslay
Sample Output
cat eh loops
Hint
Source
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; struct Tire { struct Tire* next[26]; int tag; }; char s1[100010][15],s2[15]; int main() { struct Tire *newnode(); void build(char s[15],int k,struct Tire *p); int find(char s[15],struct Tire *p); struct Tire *head; int i,j,n,m,s,t,k; t=1; head=newnode(); while(1) { gets(s2); if(strlen(s2)==0) { break; } for(i=0,j=0;i<=strlen(s2)-1;i++) { if(s2[i]!=' ') { s1[t][j++]=s2[i]; }else { break; } } s1[t][j]='\0'; for(i=i+1,j=0;i<=strlen(s2)-1;i++) { s2[j]=s2[i]; j++; } s2[j]='\0'; build(s2,t,head); t++; } while(scanf("%s",s2)!=EOF) { k=find(s2,head); if(k==0) { printf("eh\n"); }else { printf("%s\n",s1[k]); } } return 0; } struct Tire* newnode() { struct Tire *p; p=new(struct Tire); for(int i=0;i<=25;i++) { p->next[i]=NULL; } p->tag=0; return p; } void build(char s[15],int k,struct Tire *p) { int a; for(int i=0;i<=strlen(s)-1;i++) { a=s[i]-'a'; if(p->next[a]==NULL) { p->next[a]=newnode(); } p=p->next[a]; } p->tag=k; } int find(char s[15],struct Tire *p) { int a; for(int i=0;i<=strlen(s)-1;i++) { a=s[i]-'a'; if(p->next[a]!=NULL) { p=p->next[a]; }else { return 0; } } return p->tag; }