发信人: jiangsheng(蒋晟)
整理人: wenbobo(2002-12-24 09:24:41), 站内信件
|
作 者:ecai
所属论坛:Visual C++
问题点数:50
回复次数:7
发表时间:2001-3-7 10:02:00
1) PostMessage()在DEBUG版本和Release版本的区别
对于一个自定义message的handler,其标准声明形式为:
afx_msg LRESULT OnMyMessage(WPARAM wParam,LPARAM lParam);
由于我写程序时懒惰,而且通常不需要使用参数,所以经常定义成:
afx_msg void OnMyMessage();
即忽略了返回值和参数。返回值定义成void没有影响,但是如果不显式定义参数则会造成问题:在DBBUG版本中运行正常,在RELEASE版本中使用PostMessage()发送同一条自定义消息时,第二次会产生一般保护性错误!只要加上参数的显式定义就没有问题了。
请教:为什么会出现这种情况?我找遍了MSDN,似乎没有提醒注意这个问题。我写了一个很简单的程序发送两次自定义消息,证明的确会有这个问题。
2) PostMessage()不发送时耗尽资源
使用::PostMessage() (API版本的PostMessage)时,如果HWND参数为NULL时,如
UINT wParam,lParam;
。。。。。 // 给参数赋值
::PostMessage(glpMyWnd->GetSafeHwnd(),UM_MY_MESSAGE,(WPARAM)wParam,(LPARAM)lParam);
其中glpMyWnd是一个全局的CWnd指针,当相应的窗口没有打开时,实际上glpMyWnd->GetSafeHwnd()的结果为NULL。
这样实际上消息没有被处理,但是每次会消耗资源,发送多次(如100次)后资源明显减少,甚至可能会耗尽资源,如果关闭程序,则资源可以恢复正常,证明不是由于内存泄露造成。
如果我将代码修改为:
if (glpMyWnd->GetSafeHwnd())
::PostMessage(glpMyWnd->GetSafeHwnd(),UM_MY_MESSAGE,(WPARAM)wParam,(LPARAM)lParam);
即保证当glpMyWnd有效时才调用PostMessage()发送消息,则不会有问题。
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
但是我NEW了一个测试程序,试验这样的代码,却无法发现同样的情况
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
上述代码是在一个工作线程(Worker Thread)中,所以我在测试程序中也产生了一个线程,但是也没有问题
请问如何解释???
回复人:classfactory(void) (2001-3-7 11:32:00)
、如果hWnd为NULL,则消息将发到当前线程,而不是“没有处理”。如果你的工作者线程有消息队列,则每个消息将加入消息队列,只有在使用GetMessage等调用时才移去一条。如果你的线程没有这样的调用,那么这些消息永远得不到处理,当然占用内存资源了!具体察看MSDN。这种东西不要想当然,有MSDN为什么不看呢?PostMessage函数又不是你写的。
回复人:Gdj(菜鸟之王) (2001-3-7 15:23:00) 得30分
这和C的函数实现方式有关
C中函数调用时,是由调用方将参数压入堆栈,而由函数中负责将堆栈复原。
window处理消息时,调用你的函数前将参数压入堆栈,
你的函数return时没有处理的话不但会使堆栈占用变大,
而且还会在release出错(因为函数返回的地址也在堆栈中)。
debug因为加入了许多调试信息,有很多的内存是没用到的。堆栈也没有release下的紧凑,
所以一般不会报错。
回复人:Gdj(菜鸟之王) (2001-3-7 15:25:00)
这和postmessage没关系。
相当于你定义了一个函数是没有参数的。而调用时却压入了两个参数,当然要报错了。
回复人:In355Hz(好象一条狗) (2001-3-7 19:29:00) 得0分
同意Gdj的看法:
尽管WindowProc是以Pascal方式调用的,但是用afx_msg void OnMyMessage();定义的函数却是按标准C方式调用的(afx_msg 宏什么也不扩展)标准C方式要求函数自己从栈中弹出参数。如果按1中的方法做的话,如Gdj所说,肯定会有问题(至少内存泄漏)
非常感谢大家的回答,有几点补充
1)关于classfactory(void) 的回答,其实我也看了MSDN的,只是我没有考虑到worker-thread不自动产生消息队列.如果这样,使用UserInterface thread,由于它是自动产生消息队列,就应该不会有这个问题了
2)关于发送给NULL窗口的消息时耗尽资源的问题
我写了一个测试程序,建立一个worker thread,然后在里面不断的PostMessage(NULL,....)10000次,没有发现资源减少,哪位有兴趣的话请测试一下,证明的确会有这样的问题
最后说一下,我认为线程结束时会释放所占用的资源,如果PostMessage(NULL,....)10000次并等待某个事件,则会有大量资源被占用。测试已经证明了这一点。
---- Command what is yours. Conquer what is not. |
|