C 64位Windows:longjmp位于错误的位置

C 64位Windows:longjmp位于错误的位置,c,winapi,32bit-64bit,setjmp,C,Winapi,32bit 64bit,Setjmp,在Windows 64位(Windows 7)上的32位应用程序中使用longjmp时出现问题。它不是返回到上次setjmp()调用的某个点,而是在上次DispatchMessage()调用之后到达。下面是一个代码示例,如果由64位编译器编译,它可以正常工作,但在32位版本中失败 有什么解决办法吗?微软似乎对一个无关紧要的问题保持沉默: //编译为:cl a.c user32.lib kernel32.lib #包括 #包括 #包括 LRESULT回调WndProc(HWND HWND,UINT

在Windows 64位(Windows 7)上的32位应用程序中使用longjmp时出现问题。它不是返回到上次setjmp()调用的某个点,而是在上次DispatchMessage()调用之后到达。下面是一个代码示例,如果由64位编译器编译,它可以正常工作,但在32位版本中失败

有什么解决办法吗?微软似乎对一个无关紧要的问题保持沉默:

//编译为:cl a.c user32.lib kernel32.lib
#包括
#包括
#包括
LRESULT回调WndProc(HWND HWND,UINT消息,WPARAM WPARAM,LPARAM LPARAM);
jmp_buf跳转缓冲区;
int标志=0;
int main()
{
WNDCLASS wc={0,};
原子=0;
HWND-wnd;
味精;
int ret;
wc.lpfnWndProc=&WndProc;
wc.hInstance=GetModuleHandle(NULL);
wc.lpszClassName=“ExitWindows()处理程序”;
atom=寄存器类(&wc);
wnd=CreateWindow(wc.lpszClassName,wc.lpszClassName,
WS_OVERLAPPEDWINDOW、CW_USEDEFAULT、CW_USEDEFAULT、,
CW_usefault,CW_usefault,NULL,NULL,wc.hInstance,NULL);
ret=setjmp(跳转缓冲区);
开关(ret){
案例0:
展示窗口(西北、西南展示);
while(GetMessage(&msg,NULL,0,0)){
翻译信息(&msg);
发送消息(&msg);
国际单项体育联合会(旗){
printf(“不正常\n”);
打破
}
}
打破
案例1:
printf(“ok\n”);
打破
}
返回0;
}
LRESULT回调WndProc(HWND HWND,UINT消息,WPARAM WPARAM,LPARAM LPARAM)
{
开关(信息){
案例WM_油漆:
flag=1;
longjmp(跳转缓冲区,1);
返回0;
违约:
返回DefWindowProc(hWnd、message、wParam、lParam);
}
}

在WndProc中使用
longjmp
是不安全的,因为窗口过程的性质:

  • 可以通过
    SendMessage
    函数调用if,在这种情况下,它不会使用与
    setjmp
    相同的上下文(堆栈)调用。在这种情况下,我认为任何事情都可能发生…-Ok WM_油漆在正常张贴和未发送,因此不应在此处使用,即使这是不这样做的主要原因
  • 系统可以在调用窗口过程(在DispatchMessage中)之前为您准备一些内部结构,并期望能够在WndProc返回后清理它们。使用longjmp将打破这一局面
WindowProc函数上的Windows API说明:返回值是消息处理的结果,取决于发送的消息

我的理解是,窗口过程应该返回并且从不调用
exit
longjmp
。它在Windows文档中并不明确,但我不敢使用不会返回的窗口过程


正确退出消息循环的正确方法是发布WM_QUIT消息(使用PostQuitMessage函数退出消息循环)。它使
GetMessage
函数返回0,并允许系统清除在第一次调用
GetMessage

时安装的消息循环,因为您正在跨越不受您控制的代码。当使用
setjmp
/
longjmp
时,您必须确保每个人都参与其中。在您呼叫
DispatchMessage
WndProc
之间的一切都没有为这一特技做好准备。如果它在64位版本中运行,那么这只是巧合。如果goto被认为是有害的,这是什么?为什么要重新输入
main()
?如果目标是在第一次绘制时退出消息循环
ret=setjmp(跳转缓冲区)允许您在条件中测试setjmp()的“return”值,但不应在赋值中使用它。它在C标准中,因为c89,IIRC。也许是c.l.c档案/常见问题?GIYF顺便说一句:MSDN不是信息来源。(好吧,可能是关于实现或使用方面的东西)另外:你的
标志应该是不稳定的,好了。。。
// 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);
    }
}