QueueUserAPC - 抛出异常崩溃,可能的 mingw 错误
Posted
技术标签:
【中文标题】QueueUserAPC - 抛出异常崩溃,可能的 mingw 错误【英文标题】:QueueUserAPC - throwing exception crashes, possible mingw bug 【发布时间】:2012-06-23 14:44:09 【问题描述】:已解决:我从 mingw 4.6.2 升级到 4.7.0 并且运行良好,猜想这只是一个错误
我开始对如何正确终止多线程应用程序进行一些研究,我发现了关于如何使用QueueUserAPC
通知其他线程终止的那 2 个帖子(first、second)。
我想我应该试一试,当我从 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 位应用程序中为在 64 位进程中运行的线程调用 QueueApcProc
,反之亦然,但事实并非如此。
编辑:我用 Visual Studio 的 c++ 编译器 2010 编译了它,它运行完美,这可能是 gcc/mingw 中的错误?
【问题讨论】:
您正在通过一堆调用 APC 目标的内部 Windows 代码展开堆栈。只有当异常处理实现建立在本机 Windows SEH 异常之上时,这才可能奏效。它适用于 MSVC,此代码没有问题。不知道mingw用什么。它不支持捕获 SEH 异常的可能性很高以至于它不使用它。 【参考方案1】:我可以用 VS2005 重现同样的事情。问题是编译器优化了catch
。为什么?因为根据 C++ 标准,如果 extern "C"
函数因异常退出会发生什么情况是未定义的。所以编译器假定SleepEx
(即extern "C"
)永远不会抛出。在内联Test::Test
和Test::~Test
之后,它看到printf
也没有抛出,因此如果此块中的某些内容通过异常退出
Test t("thread_test");
SleepEx(INFINITE,true);
return 0;
行为未定义!
在 MSVC 中,代码不能与 Release 版本中的 /EHsc
开关一起使用,但可以与 /EHa
或 /EHs
一起使用,这告诉它假设 C 函数可能会抛出。也许 GCC 也有类似的标志。
【讨论】:
我做了一个测试,显然在使用extern "C"
声明的函数中,mingw 异常工作没有问题,并且我没有使用任何编译器优化标志
@lazy_banana: 确保尝试将 SleepEx 移动到将通过 volatile 指针间接调用的 C++ 函数中。以上是关于QueueUserAPC - 抛出异常崩溃,可能的 mingw 错误的主要内容,如果未能解决你的问题,请参考以下文章
WCF - 抛出许多许多第一次机会异常 - 然后使应用程序崩溃