在Windows 64位(Windows 7)上的32位应用程序中使用longjmp时出现问题。它不是返回到最后一次setjmp()调用的点,而是在最后一次DispatchMessage()调用之后着陆。下面是代码示例,如果由64位编译器编译,则可以正常工作,并且在32位版本时失败。
对于变通方法有什么想法吗?微软似乎对这里的一个切线问题保持沉默:https://social.msdn.microsoft.com/Forums/vstudio/en-US/b63a573f-007e-43a3-877c-b06280aa8bcc/0x80000026-application-error-when-exiting-after-using-longjmp-on-windows8-x64?forum=windowscompatibility
// Compile as: cl a.c user32.lib kernel32.lib
#include <windows.h>
#include <setjmp.h>
#include <stdio.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
jmp_buf jump_buffer;
int flag = 0;
int main()
{
WNDCLASS wc = {0, };
ATOM atom = 0;
HWND wnd;
MSG msg;
int ret;
wc.lpfnWndProc = &WndProc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = "ExitWindows() handler";
atom = RegisterClass(&wc);
wnd = CreateWindow(wc.lpszClassName, wc.lpszClassName,
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, wc.hInstance, NULL);
ret = setjmp(jump_buffer);
switch ( ret ) {
case 0:
ShowWindow(wnd,SW_SHOW);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
if ( flag ) {
printf("not ok\n");
break;
}
}
break;
case 1:
printf("ok\n");
break;
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_PAINT:
flag = 1;
longjmp(jump_buffer, 1);
return 0;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
答案 0 :(得分:2)
由于窗口过程的性质,在WndProc 中使用longjmp
不安全:
SendMessage
函数调用,在这种情况下,它不会使用与setjmp
相同的上下文(堆栈)调用。在这种情况下,我认为任何事情都可能发生...... - 好的WM_PAINT通常发布而不发送,因此不应该在这里适用,即使恕我直言,这是不这样做的主要原因WindowProc函数上的Windows API说:返回值是消息处理的结果,取决于发送的消息。
我对它的理解是,窗口过程应该返回并且永远不会调用longjmp
的{{1}}。它在Windows文档中并不明确,但我不敢使用不会返回的窗口过程。
从消息循环中正确退出的正确方法是发布WM_QUIT消息(使用PostQuitMessage函数退出消息循环)。它使exit
函数返回0并允许系统清理首次调用GetMessage
时安装的消息循环。