调试中常见Bug分析 – 内存错误(使用未初始化内存)

来源:互联网 发布:人工智能 自动控制 编辑:程序博客网 时间:2024/05/16 23:37

上次在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