QueueUserAPC - 抛出异常崩溃,可能是犯错误

时间:2012-06-23 14:44:10

标签: c++ windows multithreading winapi terminate

已解决:我从mingw 4.6.2升级到4.7.0并且运行正常,猜测它只是一个错误

我开始研究如何正确终止多线程应用程序,我找到了关于如何使用QueueUserAPC来指示其他线程终止的帖子(firstsecond

我认为我应该试一试,当我从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位。

这可能是原因吗?我读到你不应该从32位应用程序调用{​​{1}}来运行64位进程的线程,反之亦然,但情况并非如此。

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

1 个答案:

答案 0 :(得分:0)

好问题!

我没有mingw,但我可以用VS2005重现同样的事情。问题是编译器优化了catch。为什么?因为根据C ++标准,它是未定义的(或未指定的,或实现定义的...我不记得确切的公式)如果通过异常存在extern "C"函数会发生什么。因此编译器假定SleepExextern "C"并不会抛出,在内联Test::TestTest::~Test后,它会发现printf没有抛出任一个,因此如果此块中的某些内容存在异常

    Test t("thread_test");

    SleepEx(INFINITE,true);

    return 0;

行为未定义!

在MSVC中,代码不适用于Release版本中的/EHsc开关,但它可以与/EHa/EHs一起使用,这可以告诉它假设C函数可能会抛出。也许海湾合作委员会有类似的旗帜。