1

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

我开始对如何正确终止多线程应用程序进行一些研究,我发现了那两个帖子(首先关于如何使用信号通知其他线程终止、第二)。QueueUserAPC

我想我应该试一试,当我从 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 ctor\n",s);
    }

    ~Test()
    {
        printf("%s dctor\n",s);
    }
};

DWORD CALLBACK ThreadProc(void *useless)
{
    try
    {
        Test t("thread_test");

        SleepEx(INFINITE,true);

        return 0;
    }
    catch (ExitException &e)
    {
        printf("Thread exits\n%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 位的。

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

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

4

1 回答 1

1

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

    Test t("thread_test");

    SleepEx(INFINITE,true);

    return 0;

行为未定义!

在 MSVC 中,代码不能与/EHscRelease 构建中的开关一起使用,但可以与/EHaor一起使用/EHs,这告诉它假设 C 函数可能会抛出。也许 GCC 也有类似的标志。

于 2012-06-23T15:12:36.693 回答