上次在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就相当于擦桌子。