IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发工具 -> MFC踩过的一个关于空指针导致程序运行失败的坑 -> 正文阅读

[开发工具]MFC踩过的一个关于空指针导致程序运行失败的坑


1.问题描述

  • 以下窗口,未加载菜单时运行正常。

在这里插入图片描述

  • 加载完菜单提示以下内容
    在这里插入图片描述

2.分析问题

  • 代码如下,加上成员变量m_menu声明和大括号,一共才五行代码
void CTestHelperDlg::OnInitDialog(){
	... ...
	//初始化菜单
	InitMenu();
	//初始化m_tab	
	InitTabDlg();
	... ...
}


void CTestHelperDlg::InitMenu(){
	m_menu.LoadMenuA(IDR_MENU);
	SetMenu(&m_menu);
}
  • 首先怀疑是加载菜单出了问题,检查了好几遍确认没有问题。并且屏蔽加载菜单就能正常运行。又将加载菜单的代码检查了好几遍,还是没发现问题。此时刚接触MFC的我满脑子的问号。

  • 根据Visual Studio提示信息,报错出自winocc.cpp第307行。
    在这里插入图片描述

  • 此行代码m_hWnd指针为空,是系统调用执行MoveWindow函数时出的错。至此问题终于有了尽展,也确认了加载菜单没有问题。
    在这里插入图片描述

  • 打开调用堆栈发现,指向ReSize函数。ReSize是为了在调整窗口大小时,使窗口的控件自适应大小,而我自定义的函数,其中就调用了MoveWindow。
    在这里插入图片描述

  • ReSize函数代码如下,是在触发WM_SIZE消息中调用的ReSize。而在窗口初始化之前m_dlg还未创建,故m_dlg句柄为空。在m_dlg调用MoveWindow前加个空指针判断,再次运行,程序正确运行,问题解决。
    -在这里插入图片描述

  • OnSize自定义函数如下。

void CTestHelperDlg::ReSize(){
	CRect rect;
	GetClientRect(rect);
	//设置m_tab
	rect.top += 25;
	rect.bottom -= 5;
	rect.left += 5;
	rect.right -= 5;
	m_tab.MoveWindow(rect);
	//设置m_dlg
	m_tab.GetClientRect(rect);
	rect.top += 25;
	rect.bottom -= 1;
	rect.left += 1;
	rect.right -= 1;
	if(!m_dlg.m_hWnd)
		return;
	m_dlg.MoveWindow(rect);
	m_dlg.ShowWindow(SW_SHOW);

}
  • 问题虽已解决,但仍有一个疑问没得到答案:为什么加载菜单前没有触发空指针,加载菜单后反而触发了空指针?

3.再次分析

  • 又是一翻折腾发现WM_SIZE消息被触发了两次。
  • 第一次触发WM_SIZE:主窗口创建但还未创建完成时,OnSize函数中做了判断,因为主窗口m_rectDlg均为0,所以未触发ReSize。如果,没有加载菜单时WM_SIZE在程序运行前只触发这一次
void CTestHelperDlg::OnSize(UINT nType, int cx, int cy)
{
	CDialogEx::OnSize(nType, cx, cy);	

	// TODO: 在此处添加消息处理程序代码
	if(!m_rectDlg.Height()&&!m_rectDlg.Width())
		return;		
	ReSize();
}
  • 第二次触发WM_SIZE:
    1 因为加载了菜单,WM_SIZE消息又一次被触发,此时m_rectDlg已有值,故ReSize被调用。
    2 而在OnInitDialog中先加载的菜单,后加载的CTabCtrl
    3 故加载菜单时,触发WM_SIZE消息时,CTabCtrl控件上的对话框窗口m_dlg还未创建,用空指针调用MoveWindow也就出问题了。

4. 问题总结

加载菜单会额外触发一次WM_SIZE消息。

  开发工具 最新文章
Postman接口测试之Mock快速入门
ASCII码空格替换查表_最全ASCII码对照表0-2
如何使用 ssh 建立 socks 代理
Typora配合PicGo阿里云图床配置
SoapUI、Jmeter、Postman三种接口测试工具的
github用相对路径显示图片_GitHub 中 readm
Windows编译g2o及其g2o viewer
解决jupyter notebook无法连接/ jupyter连接
Git恢复到之前版本
VScode常用快捷键
上一篇文章      下一篇文章      查看所有文章
加:2022-01-12 00:12:52  更:2022-01-12 00:13:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 12:27:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码