64 位 Windows:longjmp 位于错误的位置
Posted
技术标签:
【中文标题】64 位 Windows:longjmp 位于错误的位置【英文标题】:64-bit Windows: longjmp lands in a wrong place 【发布时间】:2015-12-08 03:19:29 【问题描述】:当我在 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);
【问题讨论】:
您正在跨越不受您控制的代码。使用setjmp
/longjmp
时,您必须确保每个人都在开玩笑。在您拨打DispatchMessage
和WndProc
之间的所有事情都没有为这个噱头做好准备。如果它似乎在 64 位版本中工作,那只是巧合。
如果 goto 被认为是有害的,这是什么?你为什么要重新输入main()
?如果目标是在您获得第一次绘画时退出您的消息循环...there are better ways
ret = setjmp(jump_buffer);
您可以在 conditional 中测试 setjmp() 的“返回”值,但您不应该在作业中使用它。
它在 C 标准中,从 c89,IIRC 开始。也许 c.l.c 存档/常见问题解答? GIYF BTW:MSDN 不是信息来源。 (好吧,也许是关于实现或使用的东西)另外:你的flag
应该真的是不稳定的,
***.com/questions/16636206/… 你去...
【参考方案1】:
在 WndProc 中使用longjmp
是不安全的,因为窗口过程的性质:
SendMessage
函数调用,在这种情况下,它不会使用与setjmp
相同的上下文(堆栈)调用。在这种情况下,我认为任何事情都可能发生...... - 好的 WM_PAINT 正常发布而不发送,因此不应该在这里适用,即使恕我直言,这是不这样做的主要原因
系统可以在调用窗口过程(在 DispatchMessage 中)之前为您准备一些内部结构,并期望在 WndProc 返回后能够清除它们。使用 longjmp 会破坏这一点。
WindowProc 函数上的 Windows API 说:返回值是消息处理的结果,取决于发送的消息。
我的理解是一个窗口过程应该返回并且永远不会调用longjmp
的exit
。它在 Windows 文档中没有明确说明,但我不敢使用不会返回的窗口过程。
正确退出消息循环的正确方法是发布 WM_QUIT 消息(使用 PostQuitMessage 函数退出消息循环)。它使GetMessage
函数返回0,并允许系统清理在第一次调用GetMessage
时安装的消息循环。
【讨论】:
以上是关于64 位 Windows:longjmp 位于错误的位置的主要内容,如果未能解决你的问题,请参考以下文章
使用 Perl64 在 Windows 7(64 位)上构建 BerkeleyDB 时出现编译/链接错误
Windows 2008 R2 64 位机器 (Tridion 5.3) 上的 ComponentPresentationAssembler 错误
Windows 7 64 位 libsvm 和 python 错误:函数 'svm_get_sv_indices' 未找到