3

我目前正在调试我的一个应用程序中的崩溃,并偶然发现了一些对我来说有点奇怪的东西。在我的应用程序中,我使用 _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 再次调用线程函数本身?如果是这样,有人可以解释为什么会这样,因为对我来说这看起来很奇怪,我在想这是否指出了一些可能与我最初的线程崩溃问题有关的问题。

提前感谢您的建议。

4

0 回答 0