我今天遇到鬼了.domodal对话框报错.(来者有其分)

路人乙2019 2009-05-15 01:21:50
在一成员函数中用:
CCheckPasswdDlg passdlg;
passdlg.DoModal();
第二句报错,在其它地方都不会报错,这个CCheckPasswdDlg类绑定了一个对话框,此对话框相当简单,只有一个edit绑定了一个CString类型的变量,连onOk,OnInititdialog()等函数都没有,看图:
...全文
657 80 打赏 收藏 转发到动态 举报
写回复
用AI写文章
80 条回复
切换为时间正序
请发表友善的回复…
发表回复
hsuhuasu 2009-05-18
  • 打赏
  • 举报
回复
顶了,学习。
MichaelBomb 2009-05-18
  • 打赏
  • 举报
回复
顶了,学习。
  • 打赏
  • 举报
回复
[Quote=引用 67 楼 jameshooo 的回复:]
这里是真实的原因:
由于CWnd的特殊性,MFC使用了TLS来存储某些窗口状态,也缓存了很多永久的和临时的窗口句柄,正由于这些隐藏的方式,使得直接把一个线程中的CWnd指针传递给另一个线程中使用非常危险,两个线程操作同一个CWnd*会出现不同的状态。

不要跟我说你的工作线程没有用到主窗口的CWnd*,也许你的理由是下面的代码中根本没有使用主线程的窗口:
CCheckPasswdDlg passdlg;
passdlg.DoModal();
必须相信,这种用法真…
[/Quote]

有道理
thenshesaid 2009-05-18
  • 打赏
  • 举报
回复
[Quote=引用 64 楼 zzdmfk 的回复:]
引用 60 楼 thenshesaid 的回复:
引用 56 楼 zzdmfk 的回复:
问题已经知道是线程函数调用这个成员函数时在成员函数里this指针无效了.注意线程函数中调用的时候那个pThis->指针是有效的,要不我也跟不到成员函数内,而是进入成员函数内才无效,而在release下不会出这种情况.帮忙分析分析.

去看ASSERT_VALID宏的定义,然后Go to disassembly看是中间哪一步出错

release前面有人已经说过了,ASSERT_VALID宏在release版本中不…
[/Quote]
Sorry, 我说话也偏激
请考虑楼上的意见,如果不行的话,方便的话我可以帮你调thenshesaid@msn.com
na_he 2009-05-18
  • 打赏
  • 举报
回复
呵呵,学习了
eyoung000 2009-05-18
  • 打赏
  • 举报
回复
你重新建个工程看看,完全一样的,怀疑是你改动了工程的某些地方了吧
lyx_wq 2009-05-18
  • 打赏
  • 举报
回复
up 76
这不是鸭头 2009-05-18
  • 打赏
  • 举报
回复
跟着调试一下
raylin 2009-05-18
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 jason_wentzel 的回复:]
可能你对话框中有些控件被删除,但程序中还在引用
[/Quote]
我以前也遇到过这种情况,确实会出错.
ChanglinZhu 2009-05-18
  • 打赏
  • 举报
回复
up 学习
saintmar 2009-05-18
  • 打赏
  • 举报
回复
顶了,学习分析问题的思路!
sclz 2009-05-18
  • 打赏
  • 举报
回复
以前遇到过,好似没设置或初始化好。
doudouHuY 2009-05-18
  • 打赏
  • 举报
回复
应该会用到主线程的,默认的设置父窗口等
jameshooo 2009-05-15
  • 打赏
  • 举报
回复
这里是真实的原因:
由于CWnd的特殊性,MFC使用了TLS来存储某些窗口状态,也缓存了很多永久的和临时的窗口句柄,正由于这些隐藏的方式,使得直接把一个线程中的CWnd指针传递给另一个线程中使用非常危险,两个线程操作同一个CWnd*会出现不同的状态。

不要跟我说你的工作线程没有用到主窗口的CWnd*,也许你的理由是下面的代码中根本没有使用主线程的窗口:
CCheckPasswdDlg passdlg;
passdlg.DoModal();
必须相信,这种用法真的用到了主线程的主窗口,如果不相信,单步跟踪CDialog的构造函数和DoModal函数就知道了。只所以出现断言窗口类指针无效,是因为线程中没有缓存的窗口句柄,永久和临时的都没有,AssertValid会寻找缓存,所有受MFC管理的窗口句柄都必须保存在缓存中。

解决方案有几种:
1、把工作线程改成UI线程,即提供一个CWinThread派生类实现。
2、传递HWND,不要直接使用CWnd*,第二个线程如果想使用CWnd*,应该调用CWnd::FromHandle(hwnd)来获得临时的CWnd*。
3、用API来创建对话框,不使用MFC。
路人乙2019 2009-05-15
  • 打赏
  • 举报
回复
暂停回复,星期1再加分给分.
路人乙2019 2009-05-15
  • 打赏
  • 举报
回复
非常感谢大家.
路人乙2019 2009-05-15
  • 打赏
  • 举报
回复
[Quote=引用 60 楼 thenshesaid 的回复:]
引用 56 楼 zzdmfk 的回复:
问题已经知道是线程函数调用这个成员函数时在成员函数里this指针无效了.注意线程函数中调用的时候那个pThis->指针是有效的,要不我也跟不到成员函数内,而是进入成员函数内才无效,而在release下不会出这种情况.帮忙分析分析.

去看ASSERT_VALID宏的定义,然后Go to disassembly看是中间哪一步出错

release前面有人已经说过了,ASSERT_VALID宏在release版本中不会被编译,不会帮你做这种检查,所…
[/Quote]呵呵,本人不是科班出身.
Delta 2009-05-15
  • 打赏
  • 举报
回复
来看看,学习一下了。
逸萌 2009-05-15
  • 打赏
  • 举报
回复
[Quote=引用 56 楼 zzdmfk 的回复:]
问题已经知道是线程函数调用这个成员函数时在成员函数里this指针无效了.注意线程函数中调用的时候那个pThis->指针是有效的,要不我也跟不到成员函数内,而是进入成员函数内才无效,而在release下不会出这种情况.帮忙分析分析.
[/Quote]

[Quote=引用 44 楼 jameshooo 的回复:]
MFC多线程必须使用AfxBeginThread启动,不能使用CreateThread
[/Quote]
up

具体原因在于MFC管理窗口的机制:
在release下不会出这种情况是跳过了ASSERT,但潜在的错误还是存在的
逸萌 2009-05-15
  • 打赏
  • 举报
回复
[Quote=引用 57 楼 Conry 的回复:]
引用 39 楼 zzdmfk 的回复:
引用 35 楼 Conry 的回复:
如果是在线程函数里面的话,是会出错的

有可能,是在线程函数里调用这个成员函数的:
pThis->GetIpAddr();而这个成员函数的第一二句就是:
CCheckPasswdDlg passdlg;
passdlg.DoModal();
那我应该怎样解决呢.?

不要这样用,应该发送消息,在消息里面处理
pThis->SendMessage(WM_MYMSG,0,0);
在你的消息处理函数里面再调用GetIpAddr();
[/Quote]
up
加载更多回复(60)

15,978

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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