我在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, ¶ms);
_beginthread(Func2, 0, ¶ms);
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)
如果这太模糊,我真的很抱歉,但我不确定如何描述这一点。我会像鹰一样看这个线程,所以如果你需要什么,请告诉我。
即使它只是“可能是因为没有分配变量”而引起的,我会很高兴听到它,因为我不知道从哪里开始看。
谢谢!
答案 0 :(得分:1)
如果您在代码的各个部分中遇到随机访问冲突,那么您的堆很可能已损坏。
很难找到这些错误。首先,我建议下载适用于Windows的调试工具,并使用启用了完全堆检查的Application Verifier。请务必附加调试器(Visual Studio或windbg),因为它会在发生堆损坏时引发异常。
在那之后,你唯一能做的就是查看所有看起来可疑的代码。确保每个指针都已初始化,并且您没有访问任何超出范围的数组或容器。
如果多个线程并行写入同一个共享对象,则可能会损坏它。尝试锁定对共享对象的所有访问,特别是如果它有任何与索引相关的指针或数据。
答案 1 :(得分:1)
我注意到你有静态ProgramParams
。如果Func1
和Func2
线程开始访问它并且主线程正在写入它,这肯定会导致问题。你需要:
1)创建两份ProgramParams
副本以传递给Func1
和Func2
。请注意,这需要在堆上而不是堆栈。
2)使用关键部分使ProgramParams
线程安全。