mysql 0xc0000005_duilib菜单开发遇见“0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突”...
我的程序是这样一个逻辑。 首先创建用户列表,点击列表项弹出菜单,点击菜单上“设备选项”,弹出设备列表,上面显示这个用户拥有的设备。
菜单的创建参考了这为博主的教程:http://www.cnblogs.com/Alberl/category/520438.html
如图点击列表项,弹出菜单中点击“设备”,运行新的窗口 “设备列表”。
接下来问题出现了,上面操作重复两遍,会在第二次关闭设备列表的时候 发生异常,程序崩溃。
这就让我非常头痛了。
我知道这种错误是内存访问问题,一般都是指针操作不当造成的。
调试程序,中断发生位置是notify函数(duilib响应函数)结束位置。总之不是发生错误的位置。
下面贴出菜单程序源代码:
MenuWnd2.h:
#pragma once#include#include"my_duilib.h"#include
class CUserManageMenuWnd: publicCXMLWnd {public:explicit CUserManageMenuWnd(LPCTSTR pszXMLPath,inttag);protected:virtual ~CUserManageMenuWnd(); //私有化析构函数,这样此对象只能通过new来生成,而不能直接定义变量。就保证了delete this不会出错
public:voidInit(HWND hWndParent, POINT ptPos);virtual voidOnFinalMessage(HWND hWnd);virtualLRESULT HandleMessage (UINT uMsg, WPARAM wParam, LPARAM lParam);virtual LRESULT OnKillFocus (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&bHandled);virtual void Notify( TNotifyUI&msg );private:inttag;
};
MenuWnd2.cpp:
#include "MenuWnd2.h"#include"my_including.h"#include"page_info.h"#include"mysql_utils.h"#include"user_dev_lst.h"
externc_page_info page_info;extern user_sel_ret*user_arr;
CUserManageMenuWnd::CUserManageMenuWnd( LPCTSTR pszXMLPath,inttag)
: CXMLWnd(pszXMLPath){this->tag =tag;}
CUserManageMenuWnd::~CUserManageMenuWnd(){
}voidCUserManageMenuWnd::Init( HWND hWndParent, POINT ptPos ){
Create(hWndParent, _T("MenuWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
::ClientToScreen(hWndParent,&ptPos);
::SetWindowPos(*this, NULL, ptPos.x, ptPos.y, 0, 0, SWP_NOZORDER | SWP_NOSIZE |SWP_NOACTIVATE);
}void CUserManageMenuWnd::OnFinalMessage( HWND /*hWnd*/) {
deletethis;
}
LRESULT CUserManageMenuWnd::HandleMessage( UINT uMsg, WPARAM wParam, LPARAM lParam ) {
LRESULT lRes= 0;
BOOL bHandled=TRUE;switch( uMsg )
{caseWM_KILLFOCUS:
lRes=OnKillFocus(uMsg, wParam, lParam, bHandled);break;default:
bHandled=FALSE;
}if(bHandled ||m_PaintManager.MessageHandler(uMsg, wParam, lParam, lRes))
{returnlRes;
}return__super::HandleMessage(uMsg, wParam, lParam);
}void CUserManageMenuWnd::Notify( TNotifyUI&msg ) {intnum;stringuser_id;intdev_num;
dev_sel_ret*devs;if( msg.sType == _T("itemclick") ) {string click_menu_option = msg.pSender->GetName().ToString();if( !click_menu_option.compare(_T("check_devs")) ) {PostMessage(WM_KILLFOCUS);num= page_info.get_begin_index() + this->tag;
user_id=user_arr[num].id;
devs= MYSQL_INTERFACES::select_devs_of_user("", &dev_num, user_id);//显示该用户设备列表
create_usr_dev_lst_win(dev_num, devs);}
__super::Notify(msg);
}
LRESULT CUserManageMenuWnd::OnKillFocus( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&bHandled ) {
Close();
bHandled=FALSE;return__super::OnKillFocus(uMsg, wParam, lParam, bHandled);
}
创建菜单的代码,在user列表的notify函数里,POINT用来记录菜单生成的位置坐标:
void CUsrManageWnd::Notify( TNotifyUI&msg ) {if(msg.sType == _T("itemclick")) {int i_index = msg.pSender->GetTag();
POINT pt={msg.ptMouse.x, msg.ptMouse.y};
CUserManageMenuWnd*p_menu = new CUserManageMenuWnd(_T("Menu/menu2.xml"), i_index);
p_menu->Init(g_usr_manage_win_hwnd, pt);
p_menu->ShowWindow(TRUE);
}
__super::Notify(msg);
}
发生中断的位置就是notify函数结束的位置,真是看的我一头雾水啊,中断位置跳到反汇编来看也看不出所以然。
试了一天,最后到了晚上才发现问题所在,那就是delete。
.h文件可知,该程序私有化析构函数,使得只能new来创建,这就需要在合适时机去delete。
程序原本将delete写在OnFinalMessage函数里。但在实际调试过程中,发现在执行了OnFinalMessage函数的delete后,程序竟然又进入到notify函数里,随后报错。
我也不是很明白,为什么点击一次菜单,会进入两次notify函数,对于duilib的消息机制也不是那么精通。
最后我的解决方案,就加入一个计数的变量。进入notify创建一次设备列表,则计数变量+1。如果计数变量大于0,则不再创建设备列表。且只有计数变量大于0的时候,才执行delete。
如下,计数变量为new_win_num。
#pragma once#include#include"my_duilib.h"#include
class CUserManageMenuWnd: publicCXMLWnd {public:explicit CUserManageMenuWnd(LPCTSTR pszXMLPath,inttag);protected:virtual ~CUserManageMenuWnd(); //私有化析构函数,这样此对象只能通过new来生成,而不能直接定义变量。就保证了delete this不会出错
public:voidInit(HWND hWndParent, POINT ptPos);virtual voidOnFinalMessage(HWND hWnd);virtualLRESULT HandleMessage (UINT uMsg, WPARAM wParam, LPARAM lParam);virtual LRESULT OnKillFocus (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&bHandled);virtual void Notify( TNotifyUI&msg );private:inttag;intnew_win_num;
};
#include "MenuWnd2.h"#include"my_including.h"#include"page_info.h"#include"mysql_utils.h"#include"user_dev_lst.h"
externc_page_info page_info;extern user_sel_ret*user_arr;
CUserManageMenuWnd::CUserManageMenuWnd( LPCTSTR pszXMLPath,inttag)
: CXMLWnd(pszXMLPath){this->tag =tag;this->new_win_num = 0;
}
CUserManageMenuWnd::~CUserManageMenuWnd(){
}voidCUserManageMenuWnd::Init( HWND hWndParent, POINT ptPos ){
Create(hWndParent, _T("MenuWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
::ClientToScreen(hWndParent,&ptPos);
::SetWindowPos(*this, NULL, ptPos.x, ptPos.y, 0, 0, SWP_NOZORDER | SWP_NOSIZE |SWP_NOACTIVATE);
}void CUserManageMenuWnd::OnFinalMessage( HWND /*hWnd*/) {if (new_win_num >0)delete this;
}
LRESULT CUserManageMenuWnd::HandleMessage( UINT uMsg, WPARAM wParam, LPARAM lParam ) {
LRESULT lRes= 0;
BOOL bHandled=TRUE;switch( uMsg )
{caseWM_KILLFOCUS:
lRes=OnKillFocus(uMsg, wParam, lParam, bHandled);break;default:
bHandled=FALSE;
}if(bHandled ||m_PaintManager.MessageHandler(uMsg, wParam, lParam, lRes))
{returnlRes;
}return__super::HandleMessage(uMsg, wParam, lParam);
}void CUserManageMenuWnd::Notify( TNotifyUI&msg ) {intnum;stringuser_id;intdev_num;
dev_sel_ret*devs;if( msg.sType == _T("itemclick") ) {string click_menu_option = msg.pSender->GetName().ToString();if( !click_menu_option.compare(_T("check_devs")) ) {if (new_win_num == 0) {
PostMessage(WM_KILLFOCUS);
num= page_info.get_begin_index() + this->tag;
user_id=user_arr[num].id;
devs= MYSQL_INTERFACES::select_devs_of_user("", &dev_num, user_id);//显示该用户设备列表
create_usr_dev_lst_win(dev_num, devs);
}
new_win_num++;
}}
__super::Notify(msg);
}
LRESULT CUserManageMenuWnd::OnKillFocus( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&bHandled ) {
Close();
bHandled=FALSE;return__super::OnKillFocus(uMsg, wParam, lParam, bHandled);
}
转载一下原作者对于duilib菜单的理解https://www.cnblogs.com/Alberl/p/3352461.html,觉得讲的挺好的:
【菜单类小知识】
如果不用指针的方式,而直接用变量的方式显示菜单 CDuiMenu menu(_T("Menu/menu.xml")),则不能用ShowWindow,否则会崩溃,因为出了作用域后窗口被销毁了,所以此时可以将CDuiMenu 定义为成员变量、全局变量、或者静态变量,但是做为一个局部使用的类,这些方法显然不怎么好;
这时可以用ShowModal代替ShowWindow,于是就能看到窗口啦,但是却产生了一个问题,那就是菜单窗口不会失去焦点,或者说点击主窗口的其他区域,菜单不会消失,当然,小伙伴们可以自己捕获鼠标,来判断是否点击了主窗口的其他区域,但显然这种方法也不太好;
这个时候delete this就派上用场啦(用智能指针也会崩溃,因为出了作用域同样会销毁内存,所以只能用delete this啦~ 用delete this就是将作用域交给duilib了),据说COM里面就是用delete this来销毁内存的。Alberl在duilib的Demo里面见到了大量的delete this,觉得这种自杀的方法很不靠谱,这不,前面教程就提到了ActiveX的一个bug,也是和delete this脱不了干系的~ 不过既然COM里面都用了delete this,那就说明如果用好这把双刃剑,还是可以带来很多好处的。
因为duilib提供了一个机制,就是窗口的最后一个函数一定是OnFinalMessage,之后不再调用窗口类的其他函数,这就为自杀提供了两个必要条件;delete this而还有一个必要条件就是这个类必须是通过new来申请内存的(而非 "new[]",亦非placement的"new" ,一定要是最原始的 "new",当然malloc也行(需要用free,而不是delete)),所以就将析构函数设置成私有函数,就保证了只有通过new申请内存的方式才能编译通过。 而duilib的Demo中大量使用delete this却没有保证这些必要条件,只要直接用变量的方式来声明类,则关闭窗口时就会崩溃,作为Demo,如此不严谨,有待好好规范。 当然,没有XX党,就没有新中国,没有那些大神的Demo,也就轮不到Alberl唧唧歪歪啦,这里Alberl只是觉得Demo应该严谨和权威,毕竟是官方的,并没有其他意思,请多多谅解~O(∩_∩)O~
最后要吸取教训,如果遇到0xC0000005这种异常,一定要检查对内存的操作。数组啊、指针一类的。
也有可能是,释放了对象的对内存后继续对对象进行操作引发的。
mysql 0xc0000005_duilib菜单开发遇见“0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突”...相关推荐
- 【mfc】vs2019创建MFC基于对话框的项目没有插入任何代码运行报错:0xC0000005:读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突
发现问题: 里面一堆乱七八槽的啥几把玩意儿? 修改项目名称为英文.欧了~ 总结:项目名称别用中文!!!虽然我也不知道为啥不能用
- MFC程序提示 0xC0000005: 读取位置 0x00000020 时发生访问冲突。
这个bug困扰我两天了,我在win7下开发的MFC程序,在win7下一只运行良好,放到同事的win10机子上就出问题了,在点击按钮弹出子窗口时必崩,在win7下仔细调试才发现:调用DoModal()后 ...
- (xxx.dll)处(位于xxx.exe 中)引发的异常: 0xC0000005: 读取位置 0x0000003F 时发生访问冲突。已解决。
下面两个这种类型的报错都一样.(跟xxx.dll和xxx.exe都没关系) 0x794CECC1 (Qt5Cored.dll)处(位于 xxx.exe 中)引发的异常: 0xC0000005: 读取位 ...
- XXX处有未经处理的异常: 0xC0000374: 堆已损坏,处有未经处理的异常: 0xC0000005: 读取位置 0x4F774B16 时发生访问冲突。
XXX处有未经处理的异常: 0xC0000374: 堆已损坏,处有未经处理的异常: 0xC0000005: 读取位置 0x4F774B16 时发生访问冲突. ** 出现该问题的场景是其他公司调用我们的 ...
- 处有未经处理的异常:0xC0000005 : 读取位置 0x00000000 时发生访问冲突。
转 首先排除一种小概率事件就是系统冲突导致的,比如系统盘目录存在类似的第三方库文件,程序运行将崩溃,并报错0xC0000005 : 读取位置 0x00000000 时发生访问冲突. 上面的意思就是,你 ...
- Opencv4测试报错00007FFB3253A9C0 (ntdll.dll)处引发的异常: 0xC0000005: 读取位置 0x0000000000000010 时发生访问冲突
报错信息如下: 0x00007FFB3253A9C0 (ntdll.dll)处(位于 test1.exe 中)引发的异常: 0xC0000005: 读取位置 0x0000000000000010 时发 ...
- 0x0F1AFD76 (libcocos2d.dll) (Plane.exe 中)处有未经处理的异常: 0xC0000005: 读取位置 0x00000018 时发生访问冲突。
0x0F1AFD76 (libcocos2d.dll) (Plane.exe 中)处有未经处理的异常: 0xC0000005: 读取位置 0x00000018 时发生访问冲突. Get data fr ...
- (转载)0x0F1AFD76 (libcocos2d.dll) (Plane.exe 中)处有未经处理的异常: 0xC0000005: 读取位置 0x00000018 时发生访问冲突。
原文地址:http://blog.csdn.net/u010398774/article/details/23567441 0x0F1AFD76 (libcocos2d.dll) (Plane.exe ...
- 异常:0xC0000005: 读取位置 0x00617568 时发生访问冲突。
0xC0000005: 读取位置 0x00617568 时发生访问冲突. 这个令一个像我这种正在学习的小菜鸟非常崩溃的异常. 对于这个异常,有个大佬总结了一下: 0xC0000005可能出现的原因: ...
最新文章
- MyBatis基础知识汇总
- Selenium3自动化测试——14.操作Cookie
- 计算机类自主招生推荐信,自主招生推荐信范文:中国人民大学自主招生推荐信...
- sql两个in并列_SQL窗口函数
- canvas图形处理和进阶用法
- springboot异常处理方式
- 【脑筋急转弯】—— 谁是诚实人?
- 管家婆支持mysql_开放多接口,支持对接管家婆等第三方应用
- 开课吧之Java常见面试题之RandomAccess接口
- python打包,上传包知识点学习
- machine learning 之 Neural Network 3
- excel npoi 连接_Asp.Net使用Npoi导入导出Excel的方法
- jspx框架使用总结-页面开发
- UE4骨骼动画新手入门
- 周杰伦录音室专辑名字整理,时间倒数
- P1548 [NOIP1997 普及组] 棋盘问题
- 你还会“袖手旁观”吗?
- linux 操作excel文件,Linux下输出excel文件
- 为 a.out 举行一个特殊的告别仪式
- Python 毕设精品实战案例——快速索引目录
热门文章
- minio 单机版安装
- “银行家算法”讲解,在前端表格中利用自定义公式实现“四舍六入五成双”
- 2022年水彩笔市场前景分析及研究报告
- FDFS上传文件报错 tracker_query_storage fail, error no: 2, error info: No such file or directo
- vi下Makefile的自动生成
- 宜信区块链实践-案例及探索
- 达梦数据库——Oracle到达梦数据迁移
- luoguP4098「HEOI2013」ALO
- To_Heart—题解——[HEOI2013]ALO
- 影评《北京爱情故事》告诉我们一些事