例如:定义一个成员变量
CWinThread *m_pWinThread;
如果没有在程序末尾删除这个指针,delete m_pWinThread; 则会出现
Detected Memory leaks! 的错误。
2. 线程需要关闭 TerminateThread
3. Socket so对象需要被关闭 closesocket(so)
否则会出现内存泄漏错误。
///
CWinThread *m_pWinThread;
启动线程时
m_pWinThread=AfxBeginThread(TestServ,(LPVOID)this);
退出应用程序使用(可以把着段代码写在窗口销毁的函数DestroyWindow()中)
void CThreadtestDlg::OnOK()
{
if(m_pWinThread!=NULL){
if(m_pWinThread->m_hThread!=NULL){
DWORD dwExitCode=0;
GetExitCodeThread(m_pWinThread->m_hThread,&dwExitCode);
if(dwExitCode==STILL_ACTIVE){
TerminateThread(m_pWinThread->m_hThread,0);
}
delete m_pWinThread;
}
}
CDialog::OnOK();
}
//
大家经常听到一个名词叫内存泄漏。到底怎样才会遇到内存泄漏,内存泄漏到底该怎么定位,大家却都很糊涂。实际上我对这个问题也很头疼,下面就是我关于这个问题的一些小看法:
1. 什么叫内存泄漏?
内存泄漏是指你分配了内存,使用完毕后没有正确释放它。这样这个内存就不能再被使用。
例如:
void test()
{
char * p = new char[MAX_PATH];
GetModuleFileName(NULL,p, MAX_PATH);
strcat(p+strlen(p) - 3, "txt");
CStdioFile file(p);
file.WriteString("text");
file.Close();
}
注意:上面的指针p函数退出后就无法再释放,new char[MAX_PATH]分配的内存就泄漏了。
2. 何时我的程序泄漏了?
从外部看,我们很难100%准确的方法去判断是否有内存泄漏。实际上,一块内存是否被泄漏,从外部看只有当进程结束才能知道。因为你完全可以从开始分配一块内存,直到结束才去释放它。
基本上,下面行为不能说明内存泄漏:
a) 任务管理器上显示内存使用增加了1MB
b) 内存使用很多(我见过最大内存使用超过1.5GB的程序)
下面行为可能意味着有内存泄漏:
a) 一个进程的内存使用量按照一个固定的速度稳定的增长(例如每小时增加20MB)
如果可以在VC IDE中运行程序,当程序退出时,系统会报一堆泄漏错误。
3. 如何定位
从编译器角度讲,在分配内存后,任何时候释放都是合适的,因此系统不会知道你何时适合去释放内存。在进程运行过程中,你只能估计是否有内存泄漏,而不能确定一定有内存泄漏。一般来说,我们可以用以下一些办法定位:
a) 使用性能监视器跟踪进程的内存使用情况,如果它在不断增长,且增长速度趋于稳定,一般说明在某个循环性的操作中有内存泄漏
b) 在编译器中按照Debug模式运行程序,运行一定时间后(例如2天),使用正常的方式停止进程
正常情况下,你不会收到任何和内存有关的异常。如果你程序有内存泄漏,你会收到如下错误信息:
Detected memory leaks!
Dumping objects ->
D:\projects\EnumWnd\EnumWndDlg.cpp(185) : {78} normal block at 0x00421330, 100 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
注意,这里EnumWndDlg.cpp(185)应该是分配这块内存的地方。这是因为没有所谓的内存泄漏点,只有在某点分配的内存被泄漏了。
4. 如何分析内存泄漏
内存泄漏分析一般是通过分析内存生命周期来进行的。你必须对你的内存的可能使用情况有所了解。在此基础上,你应该了解在那个地方内存应该被释放。如果有内存泄漏,说明程序没有走到那个地方,或者释放代码没有正确执行。因此你可能需要跟踪你代码的执行情况,通过分析为什么代码没有按照预期走到内存释放处,了解为什么内存泄漏了。
常见的原因:
a) 忘记释放
b) 释放的方法错误
例如:把指针加入诸如CArray之类的集合对象中,释放时应该首先通过delete操作删除指针指向的对象,然后才能去调用诸如RemoveAll函数去释放集合中的指针。单纯析构诸如CArray之类的对象,不会自动释放它所包含的指针所指向的对象。
c) 析构函数错误:如果你对象中包含指针,那么你析构函数需要正确的释放这些指针。如果你析构函数不做这些,就会有内存泄漏
d) 线程问题:如果线程被你通过TerminateThread中止,那么它所分配的对象一般不会有机会被释放。这是那些喜欢在线程外中止线程的人经常遇到的问题。