队列用户APC - 抛出异常崩溃,可能是 mingw 错误

QueueUserAPC - throwing exception crashes, possible mingw bug

本文关键字:mingw 错误 崩溃 用户 APC 抛出异常 队列      更新时间:2023-10-16

已解决:我从mingw 4.6.2升级到4.7.0,它运行良好,猜猜这只是一个错误

开始对如何正确终止多线程应用程序进行一些研究,我发现了关于如何使用QueueUserAPC向其他线程发出终止信号的 2 篇帖子(第一、第二篇)。

我想我应该试一试,当我从 APCProc 抛出异常时,应用程序不断崩溃。

法典:

#include <stdio.h>
#include <windows.h>
class ExitException
{
public:
    char *desc;
    DWORD exit_code;
    ExitException(char *desc,int exit_code): desc(desc), exit_code(exit_code)
    {}
};
//I use this class to check if objects are deconstructed upon termination
class Test 
{
public:
    char *s;
    Test(char *s): s(s)
    {
        printf("%s ctorn",s);
    }
    ~Test()
    {
        printf("%s dctorn",s);
    }
};
DWORD CALLBACK ThreadProc(void *useless)
{
    try
    {
        Test t("thread_test");
        SleepEx(INFINITE,true);
        return 0;
    }
    catch (ExitException &e)
    {
        printf("Thread exitsn%s %lu",e.desc,e.exit_code);
        return e.exit_code;
    }
}
void CALLBACK exit_apc_proc(ULONG_PTR param)
{
    puts("In APCProc");
    ExitException e("Application exit signal!",1);
    throw e;
    return;
}
int main()
{
    HANDLE thread=CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
    Sleep(1000);
    QueueUserAPC(exit_apc_proc,thread,0);
    WaitForSingleObject(thread,INFINITE);
    puts("main: bye");
    return 0;
}

我的问题是为什么会发生这种情况?

我使用 mingw 进行编译,我的操作系统是 64 位。

这是原因吗?我读到您不应该从 32 位应用程序调用 64 位进程中运行的线程QueueApcProc,反之亦然,但情况并非如此。

编辑:我用Visual studio的c ++编译器2010编译了这个,它完美地工作,这可能是gcc/mingw中的一个错误?

我可以用VS2005重现同样的事情。问题是编译器优化了catch。为什么?因为根据C++标准,如果extern "C"函数异常退出会发生什么,这是未定义的。因此,编译器假定SleepExextern "C")永远不会抛出。在内联Test::TestTest::~Test后,它看到printf也不会抛出,因此如果此块中的某些内容通过异常退出

    Test t("thread_test");
    SleepEx(INFINITE,true);
    return 0;

行为未定义!

在 MSVC 中,代码不适用于发布版本中的/EHsc开关,但适用于 /EHa/EHs ,这告诉它假设 C 函数可能会抛出。也许海湾合作委员会也有类似的标志。