消息循环是一个无限的for循环,那么程序还怎么响应发送的消息呀?

chenzhu 2009-03-24 12:54:21
  刚学习vc,建了一个简单的对话框程序,试验一下发送消息和寄送消息时,看到程序一开始就运行在无限消息循环for (;;)里面,但是一旦响应发送消息,程序立刻就跳出这个消息循环,真是不明白呀,请各位大大帮我解惑,下面是发送消息和寄送消息的调用堆栈。


寄送消息时:



mfc71d.dll!AfxInternalPumpMessage() Line 183 + 0x18 C++
mfc71d.dll!CWinThread::PumpMessage() Line 916 C++
mfc71d.dll!AfxPumpMessage() Line 195 + 0xb C++
//由下可见程序应该一直运行在无限消息循环for (;;)里面啊
mfc71d.dll!CWnd::RunModalLoop(unsigned long dwFlags=4) Line 4566 + 0x5 C++
mfc71d.dll!CDialog::DoModal() Line 527 + 0xc C++
test1.exe!Ctest1App::InitInstance() Line 58 + 0xb C++
mfc71d.dll!AfxWinMain(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ *
test1.exe!WinMain(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ * hPrevInstance=0x00000000,
test1.exe!WinMainCRTStartup() Line 390 + 0x39 C
kernel32.dll!7c816fd7()
ntdll.dll!7c935b4f()



发送消息时:



mfc71d.dll!CWnd::OnWndMsg(unsigned int message=273, unsigned int wParam=1, long
mfc71d.dll!CWnd::WindowProc(unsigned int message=273, unsigned int wParam=1, long
mfc71d.dll!AfxCallWndProc(CWnd * pWnd=0x0012fe3c, HWND__ * hWnd=0x0028016e, unsigned int
mfc71d.dll!AfxWndProc(HWND__ * hWnd=0x0028016e, unsigned int nMsg=273, unsigned int wParam=1,
mfc71d.dll!AfxWndProcBase(HWND__ * hWnd=0x0028016e, unsigned int nMsg=273, unsigned int
user32.dll!77d18734()
user32.dll!77d18816()
user32.dll!77d1b4c0()
user32.dll!77d1b89b()
user32.dll!77d1b903()
user32.dll!77d4fd1d()
user32.dll!77d46561()
user32.dll!77d26df4()
mfc71d.dll!AfxGetModuleThreadState() Line 243 C++
mfc71d.dll!AfxGetThread() Line 142 + 0x5 C++
//根本就没有在无限消息循环for (;;)里面



  响应发送消息时程序怎么就跳出了无限消息循环for (;;),怎么回事呀?
...全文
427 17 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
chenzhu 2009-03-27
  • 打赏
  • 举报
回复
多谢w_anthony的详细解答,20分全部奉上。
确实调用堆栈前面那部分没有显示出来,但我觉得应该是vc有意把它分开的,我引入符号文件以后,发现没有显示的那部分是按钮接受寄送的LButtonUp消息的处理过程,也是在无限的for循环里面从取队列消息开始的。
chenzhu8 2009-03-26
  • 打赏
  • 举报
回复
我觉得应该不是调试工具有问题,可能和用户模式和内核模式的有关系,正在求解~~~
w_anthony 2009-03-26
  • 打赏
  • 举报
回复
我说LS你不会SHIFT+F11几次,求证一下吗?“我觉得”有什么问题,大胆假设,小心求证嘛……
算了,你给你写个调试工具犯傻例子:

__declspec(naked) void func()
{
_asm
{
mov eax, ebp
xor ebp, ebp
mov ebp, eax ;断点加在这里,断下后你会看到调用堆栈乱了
retn
}
}

int main(int, char**)
{
func();
return 0;
}

Sharp1070329152 2009-03-25
  • 打赏
  • 举报
回复
有PeekMessage?
robert_duan 2009-03-25
  • 打赏
  • 举报
回复
不懂.帮顶.
w_anthony 2009-03-25
  • 打赏
  • 举报
回复
至于调试工具犯傻的原因,我以前研究过,似乎是如果函数不用ebp来保存esp,那么调用堆栈就会乱掉,你遇到的这个我没有研究过,你调试的时候也仔细观察一下吧。
w_anthony 2009-03-25
  • 打赏
  • 举报
回复
看来LZ以前对C++调试也颇有心得,知道用调用堆栈来观察调用顺序关系。
LS几位说的都没有错,确实没有出循环。
那么你看到的调用堆栈是怎么回事呢?我个人认为是调试工具犯傻了,你可以在第二次断点断下后,shift+F11逐层返回,返回几次到user32.dll里面的调用以后,就可以看到原来的堆栈调用关系了。
chenzhu 2009-03-25
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 qiangorqiang 的回复:]
并不是跳出了循环,而是在循环中调用了消息的处理函数。
[/Quote]

我觉得可能也是在循环里面调用消息的处理函数,而不是退出循环,那么谁能解释一下为什么发送消息时的调用堆栈和寄送消息时不一样?
mengde007 2009-03-24
  • 打赏
  • 举报
回复
在循环里面执行了另一个函数,然后回来继续循环等待消息。不然的话,要是有其它消息,该怎么办呢
chenzhu 2009-03-24
  • 打赏
  • 举报
回复
应该是跳出了那个无限消息循环for (;;),不然的话发送消息时的调用堆栈应该要从循环那里开始的,不是么?
bitwwzhang130 2009-03-24
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 qiangorqiang 的回复:]
并不是跳出了循环,而是在循环中调用了消息的处理函数。
[/Quote]
同意
danxuezx 2009-03-24
  • 打赏
  • 举报
回复
消息循环是有退出条件的
qiangorqiang 2009-03-24
  • 打赏
  • 举报
回复
并不是跳出了循环,而是在循环中调用了消息的处理函数。
jlj84237485 2009-03-24
  • 打赏
  • 举报
回复
帮顶一下
elmnd 2009-03-24
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 qiangorqiang 的回复:]
并不是跳出了循环,而是在循环中调用了消息的处理函数。
[/Quote]

for(;;)
{
if(xx) break;
}
//这样还是死循环, 不过有退出条件而已
qiangorqiang 2009-03-24
  • 打赏
  • 举报
回复
可以做个实验。在消息处理函数中进行死循环,这时窗体将无法刷新。从这里可以看出,如果消息处理函数没有返回,消息循环就不能处理消息。
galafx 2009-03-24
  • 打赏
  • 举报
回复
我对这东西不了解,只说下for循环。

在for循环里执行函数会跳出循环,执行函数部分.

函数执行完后在跳回来继续执行for循环

16,548

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧