上次在MSDN论坛上看见一个网友问ZeroMemory的用处,问题里面说他在内存上分配了一个变量,但是在使用它调用一个函数的时候,系统报告Access Violation异常,但是加上ZeroMemory以后,就运行正常了,因此他想知道ZeroMemory的用处。
// 使用未初始化变量.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
STARTUPINFO info;
PROCESS_INFORMATION pi;
ZeroMemory(&info, sizeof(info));
ZeroMemory(&pi, sizeof(pi));
info.cb = sizeof(info);
BOOL result = ::CreateProcess(NULL,
argv[1],
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&info,
&pi);
if ( !result )
{
wprintf(L"CreateProcess returns %d\n", GetLastError());
return -1;
}
else
{
::WaitForSingleObject(pi.hProcess, INFINITE);
::CloseHandle(pi.hProcess);
::CloseHandle(pi.hThread);
wprintf(L"CreateProcess succeeded\n");
return 0;
}
}
|
比如上面的代码,如果将两个ZeroMemory语句注释掉的话,在调试器里面调用CreateProcess函数的时候,你会得到一个Access Violation异常,如下图所示:

堆栈看起来象下面这样:
ntdll.dll!7c9212b0()
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
kernel32.dll!7c81a4c8()
kernel32.dll!7c819da8()
ntdll.dll!7c92d5bc()
ntdll.dll!7c98d160()
ntdll.dll!7c969564()
ntdll.dll!7c93cd5b()
ntdll.dll!7c93947a()
ntdll.dll!7c938f01()
ntdll.dll!7c9476ea()
ntdll.dll!7c938f01()
ntdll.dll!7c947764()
ntdll.dll!7c98d994()
ntdll.dll!7c969e1c()
ntdll.dll!7c947764()
ntdll.dll!7c97d414()
kernel32.dll!7c802362()
> 使用未初始化变量.exe!wmain(int argc=2, wchar_t * * argv=0x00393250) Line 25 + 0x25 bytes C++
使用未初始化变量.exe!__tmainCRTStartup() Line 579 + 0x19 bytes C
使用未初始化变量.exe!wmainCRTStartup() Line 399 C
kernel32.dll!7c817067()
|
Windows在给你的变量分配内存的时候,只是划定一块内存区域给变量,由于物理内存是操作系统里面所有进程共享的资源,所以分配的内存区域有可能刚刚被其他程序释放掉--而这些程序写入到那一段内存的数据还没有被清空,因此如果你不用ZeroMemory将刚刚分配的内存清零的话,读取一段被其他程序写入的数据对你的程序而言是一堆垃圾,这就是为什么有的时候会出现AccessViolation的原因。
就好比你去一个很忙的餐厅吃饭,服务员把你领到一个桌子前,这个桌子需要被擦干净你才能用一样,ZeroMemory就相当于擦桌子。
一般来说,分配结构体变量,都需要使用ZeroMemory
|