在代码的不同部分中获取访问冲突错误

时间:2011-11-27 05:22:07

标签: c++ visual-studio-2010 winapi

我在win32应用程序中遇到了这些随机访问冲突,并且完全不知道是什么导致它。我可以发布代码,但它在不同的部分,并且会太长。但是,我想我知道问题可能是什么:

基本上,我们有一个wndproc:

LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
    static ProgramParams params;

    switch(msg) {
        case WM_CREATE:
            params.hwnd = hwnd;
            params.connected = TRUE;
            //more params assignment here
            return 0;

        case WM_RUNTHREADS:
            _beginthread(Func1, 0, &params);
            _beginthread(Func2, 0, &params);
            return 0;

        case WM_DISCONNECT:
            params.connected = FALSE;
            return 0;

// lot more code
}

在Func1和Func2中,指向params的指针被大量使用。严重来说,我指的是多个赋值和if语句。我不确定这是不是一个坏主意,但我觉得这种用法导致了问题。它就像一个将所有线程连接在一起的全局变量。

以下是反汇编的一些摘录:

dc final v2.exe中0x77c815ee处的未处理异常:0xC0000005:访问冲突。

    return TRUE;
001E3AE5  mov         eax,1  
}
001E3AEA  push        edx  
001E3AEB  mov         ecx,ebp  
001E3AED  push        eax  
001E3AEE  lea         edx,[ (1E3B10h)]  
001E3AF4  call        @ILT+220(@_RTC_CheckStackVars@8) (1E10E1h)  
----> 001E3AF9  pop         eax  //green arrow (after clicking "break") pointing here
001E3AFA  pop         edx  
001E3AFB  pop         edi  
001E3AFC  pop         esi  
001E3AFD  pop         ebx  
001E3AFE  add         esp,0E8h  
001E3B04  cmp         ebp,esp  
001E3B06  call        @ILT+610(__RTC_CheckEsp) (1E1267h)  
001E3B0B  mov         esp,ebp  
001E3B0D  pop         ebp  
001E3B0E  ret  

围绕地址0x77c815ee组装

77C815C3  nop  
77C815C4  mov         eax,12Eh  
77C815C9  xor         ecx,ecx  
77C815CB  lea         edx,[esp+4]  
77C815CF  call        dword ptr fs:[0C0h]  
77C815D6  add         esp,4  
77C815D9  ret         18h  
77C815DC  mov         eax,12Fh  
77C815E1  xor         ecx,ecx  
77C815E3  lea         edx,[esp+4]  
77C815E7  call        dword ptr fs:[0C0h]  
----> 77C815EE  add         esp,4 
77C815F1  ret         0Ch  
77C815F4  mov         eax,130h  
77C815F9  xor         ecx,ecx  
77C815FB  lea         edx,[esp+4]  
77C815FF  call        dword ptr fs:[0C0h]  
77C81606  add         esp,4  
77C81609  ret         18h  
77C8160C  mov         eax,131h  
77C81611  xor         ecx,ecx  
77C81613  lea         edx,[esp+4]  
77C81617  call        dword ptr fs:[0C0h]  

通过调试打开所有异常>例外情况导致:

dc final v2.exe中的0x00000000处的第一次机会异常:0xC0000005:访问冲突。

SendMessage(parentHwnd, WM_TERM, (WPARAM) "ABCD", NULL);
001F1CAF  mov         esi,esp  
001F1CB1  push        0  
001F1CB3  push        465h  
001F1CB8  push        402h  
001F1CBD  mov         eax,dword ptr [pparams]  
001F1CC0  mov         ecx,dword ptr [eax]  
001F1CC2  push        ecx  
001F1CC3  call        dword ptr [__imp__SendMessageW@16 (1FE68Ch)]  
----> 001F1CC9  cmp         esi,esp //green arrow here
001F1CCB  call        @ILT+610(__RTC_CheckEsp) (1F1267h)  

如果这太模糊,我真的很抱歉,但我不确定如何描述这一点。我会像鹰一样看这个线程,所以如果你需要什么,请告诉我。

即使它只是“可能是因为没有分配变量”而引起的,我会很高兴听到它,因为我不知道从哪里开始看。

谢谢!

2 个答案:

答案 0 :(得分:1)

如果您在代码的各个部分中遇到随机访问冲突,那么您的堆很可能已损坏。

很难找到这些错误。首先,我建议下载适用于Windows的调试工具,并使用启用了完全堆检查的Application Verifier。请务必附加调试器(Visual Studio或windbg),因为它会在发生堆损坏时引发异常。

在那之后,你唯一能做的就是查看所有看起来可疑的代码。确保每个指针都已初始化,并且您没有访问任何超出范围的数组或容器。

如果多个线程并行写入同一个共享对象,则可能会损坏它。尝试锁定对共享对象的所有访问,特别是如果它有任何与索引相关的指针或数据。

答案 1 :(得分:1)

我注意到你有静态ProgramParams。如果Func1Func2线程开始访问它并且主线程正在写入它,这肯定会导致问题。你需要:

1)创建两份ProgramParams副本以传递给Func1Func2。请注意,这需要在堆上而不是堆栈。

2)使用关键部分使ProgramParams线程安全。