我正在调试我的一个应用程序中的崩溃,并偶然发现了一些对我来说有点奇怪的事情。 在我的应用程序中,我使用_beginthreadex函数启动了几个线程。在某个随机时间点(有时在几个小时之后),其中一个线程因未知原因而崩溃。崩溃时的堆栈跟踪如下所示:
my.dll!thread(void * p=0x241e0140) Line 792 + 0xf bytes C
msvcr90.dll!__endthreadex() + 0x44 bytes
msvcr90.dll!__endthreadex() + 0xd8 bytes
kernel32.dll!_BaseThreadStart@8() + 0x37 bytes
其中thread是我的线程的主循环函数。我在这里省略了我的线程函数之上的堆栈帧。崩溃是一种访问冲突,每次都在同一位置发生,并且具有完全相同的错误指针值。
现在让我想到的是__endthreadex出现在堆栈跟踪中。我试图在一个小的示例程序中重现这一点,并在那里导致访问冲突。但是堆栈跟踪看起来不同:
test.exe!thread(void * vpb=0x00000000) Line 9 + 0x3 bytes C++
test.exe!_callthreadstartex() Line 348 + 0x6 bytes C
test.exe!_threadstartex(void * ptd=0x000328e8) Line 326 + 0x5 bytes C
kernel32.dll!_BaseThreadStart@8() + 0x37 bytes
相应的代码是:
static unsigned __stdcall thread( void * vpb )
{
int *a = (int*)0xdeadbeef;
*a = 0;
return 1;
}
int main()
{
HANDLE th = (HANDLE)_beginthreadex( NULL, 0, thread, 0, CREATE_SUSPENDED, NULL );
for(int i=0; i<INT_MAX;)
{
++i;
}
ResumeThread(th);
for(int i=0; i<INT_MAX;)
{
++i;
}
return 0;
}
原始代码与此类似,但显然更复杂。所以我不知道堆栈跟踪中的差异是否可能是由于我在实现小例子时对代码的修改造成的,或者所有这些都表明堆栈损坏存在问题。
所以我的问题基本上是:_BaseThreadStart是否可能调用__endthreadex再次调用线程函数本身?如果是这样,有人可以解释为什么会出现这种情况,因为对我来说这看起来很奇怪,而且我在想这是否指出了一些可能与我最初的崩溃线程问题有关的问题。
提前感谢您的建议。