duilib菜单开发遇见“0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突”
我的程序是这样一个逻辑。 首先创建用户列表,点击列表项弹出菜单,点击菜单上“设备选项”,弹出设备列表,上面显示这个用户拥有的设备。
菜单的创建参考了这为博主的教程:http://www.cnblogs.com/Alberl/category/520438.html
如图点击列表项,弹出菜单中点击“设备”,运行新的窗口 “设备列表”。
接下来问题出现了,上面操作重复两遍,会在第二次关闭设备列表的时候 发生异常,程序崩溃。
这就让我非常头痛了。
我知道这种错误是内存访问问题,一般都是指针操作不当造成的。
调试程序,中断发生位置是notify函数(duilib响应函数)结束位置。总之不是发生错误的位置。
下面贴出菜单程序源代码:
MenuWnd2.h:
#pragma once #include <windows.h>
#include "my_duilib.h"
#include <iostream> class CUserManageMenuWnd: public CXMLWnd {
public:
explicit CUserManageMenuWnd(LPCTSTR pszXMLPath,int tag); protected:
virtual ~CUserManageMenuWnd(); // 私有化析构函数,这样此对象只能通过new来生成,而不能直接定义变量。就保证了delete this不会出错 public:
void Init(HWND hWndParent, POINT ptPos);
virtual void OnFinalMessage(HWND hWnd);
virtual LRESULT HandleMessage (UINT uMsg, WPARAM wParam, LPARAM lParam);
virtual LRESULT OnKillFocus (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
virtual void Notify( TNotifyUI& msg );
private:
int tag;
};
MenuWnd2.cpp:
#include "MenuWnd2.h"
#include "my_including.h"
#include "page_info.h"
#include "mysql_utils.h"
#include "user_dev_lst.h" extern c_page_info page_info;
extern user_sel_ret* user_arr; CUserManageMenuWnd::CUserManageMenuWnd( LPCTSTR pszXMLPath, int tag)
: CXMLWnd(pszXMLPath){
this->tag = tag;
} CUserManageMenuWnd::~CUserManageMenuWnd(){
} void CUserManageMenuWnd::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, , , SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
} void CUserManageMenuWnd::OnFinalMessage( HWND /*hWnd*/ ) {
delete this;
} LRESULT CUserManageMenuWnd::HandleMessage( UINT uMsg, WPARAM wParam, LPARAM lParam ) {
LRESULT lRes = ;
BOOL bHandled = TRUE; switch( uMsg )
{
case WM_KILLFOCUS:
lRes = OnKillFocus(uMsg, wParam, lParam, bHandled);
break;
default:
bHandled = FALSE;
} if(bHandled || m_PaintManager.MessageHandler(uMsg, wParam, lParam, lRes))
{
return lRes;
} return __super::HandleMessage(uMsg, wParam, lParam);
} void CUserManageMenuWnd::Notify( TNotifyUI& msg ) {
int num;
string user_id;
int dev_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 <windows.h>
#include "my_duilib.h"
#include <iostream> class CUserManageMenuWnd: public CXMLWnd {
public:
explicit CUserManageMenuWnd(LPCTSTR pszXMLPath,int tag); protected:
virtual ~CUserManageMenuWnd(); // 私有化析构函数,这样此对象只能通过new来生成,而不能直接定义变量。就保证了delete this不会出错 public:
void Init(HWND hWndParent, POINT ptPos);
virtual void OnFinalMessage(HWND hWnd);
virtual LRESULT HandleMessage (UINT uMsg, WPARAM wParam, LPARAM lParam);
virtual LRESULT OnKillFocus (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
virtual void Notify( TNotifyUI& msg );
private:
int tag;
int new_win_num;
};
#include "MenuWnd2.h"
#include "my_including.h"
#include "page_info.h"
#include "mysql_utils.h"
#include "user_dev_lst.h" extern c_page_info page_info;
extern user_sel_ret* user_arr; CUserManageMenuWnd::CUserManageMenuWnd( LPCTSTR pszXMLPath, int tag)
: CXMLWnd(pszXMLPath){
this->tag = tag;
this->new_win_num = ;
} CUserManageMenuWnd::~CUserManageMenuWnd(){
} void CUserManageMenuWnd::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, , , SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
} void CUserManageMenuWnd::OnFinalMessage( HWND /*hWnd*/ ) {
if (new_win_num >)
delete this;
} LRESULT CUserManageMenuWnd::HandleMessage( UINT uMsg, WPARAM wParam, LPARAM lParam ) {
LRESULT lRes = ;
BOOL bHandled = TRUE; switch( uMsg )
{
case WM_KILLFOCUS:
lRes = OnKillFocus(uMsg, wParam, lParam, bHandled);
break; default:
bHandled = FALSE;
} if(bHandled || m_PaintManager.MessageHandler(uMsg, wParam, lParam, lRes))
{
return lRes;
} return __super::HandleMessage(uMsg, wParam, lParam);
} void CUserManageMenuWnd::Notify( TNotifyUI& msg ) {
int num;
string user_id;
int dev_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 == ) {
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,觉得讲的挺好的:
最后要吸取教训,如果遇到0xC0000005这种异常,一定要检查对内存的操作。数组啊、指针一类的。
也有可能是,释放了对象的对内存后继续对对象进行操作引发的。
duilib菜单开发遇见“0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突”的更多相关文章
- 调试器地址出现大小端紊乱,引发的异常: 0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突。
今天在编写一系列新增需求代码后,开始调试代码 发现上个版本正常可运行的代码出现了:引发的异常: 0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突. 上个版本数代码 ...
- 0x00007FFC8C5325E7 (ucrtbased.dll)处(位于 DataStructure.exe 中)引发的异常: 0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突。
此处为非“%s” 类型数据以“%s”类型打印错误. 需要仔细检查代码中数据类型错误.
- 0xC0000005: 读取位置 0x00000000 时发生访问冲突
遇见这种问题一般都是空指针,即:指针里没有赋值~ 如果你对null 进行操作就会产生空指针异常 Object obj = new Object(); 你要知道 obj是一个Object指针变量,指向O ...
- 启动MFC程序的时候报错:0xC0000005: 读取位置 0x00000000 时发生访问冲突
此程序的结构是 MouseCap.h #pragma once #include <afxwin.h> class MouseCapApp : public CWinApp { publi ...
- xx.exe 中的 0x014180bd 处有未经处理的异常: 0xC0000005: 读取位置 0xfeeefeee 时发生访问冲突(当指针访问异常时,应考虑是不是对象未创建)。
xx.exe 中的 0x014180bd 处有未经处理的异常: 0xC0000005: 读取位置 0xfeeefeee 时发生访问冲突
- vc++,MFC,组合框控件设置时0xC0000005: 读取位置 0x00000020 时发生访问冲突
511.exe 中的 0x78bb5dec (mfc90ud.dll) 处未处理的异常: 0xC0000005: 读取位置 0x00000020 时发生访问冲突 _AFXWIN_INLINE int ...
- 【MFC】0xC0000005: 读取位置 0x00000020 时发生访问冲突
原因:使用GetDlgItem()函数时需要先判断指针然后才可以使用. 错误代码: //重新建一个线程,查询帧同步 DWORD WINAPI SCsync_Thread(LPVOID Lparam) ...
- 程序运行时 0xC0000005: 读取位置 0x00000000 时发生访问冲突 ,可能是 com 组件引入各种问题
在使用com组件事,可能引入很多不是问题的问题,比如CString 定义出运行时出错等等,这些问题解决的办法就是初始化组件 然后释放组件, 在使用组件时,如果仅仅用在按钮事件或者别的mfc 对话框类里 ...
- 读取位置 0xcccccccc 时发生访问冲突
XXXXX.exe 中的 0x1004eec2 处有未经处理的异常: 0xC0000005: 读取位置 0xcccccccc 时发生访问冲突 DEBUG模式下总是出现此错误,改为Release模式,错 ...
随机推荐
- JDBC连接数据库中CallableStatement执行有参存储过程及注解其他
Oracle的建有参存储过程的过程 procedure pro_01(v_01 in number,v_02 out varchar2) as begin select name into v_02 ...
- NOIP 模拟 玩积木 - 迭代加深搜索 / bfs+hash+玄学剪枝
题目大意: 有一堆积木,0号节点每次可以和其上方,下方,左上,右下的其中一个交换,问至少需要多少次达到目标状态,若步数超过20,输出too difficult 目标状态: 0 1 1 2 2 2 3 ...
- BZOJ 1090 - 区间dp
Magic Door 题目大意: 给一个字符串,可以将重复的串缩成x(a),表示x个a,求能缩成的最小长度. 题目分析 区间dp: dp[i][j]表示i~j处理后的最小长度, 则有 \[dp[i][ ...
- 病毒软件,导致DNS失效的解决办法
问题症状,DNS失效了,ping域名总是失败. 问题回顾:几个周之前,某群友在群里上传了一个病毒软件,我想去测验下,最后果然中毒.前几天,把软件卸载了,上周末解决了删除最后一款软件导致无法上网的问题. ...
- Tomcat启动失败问题解决
1. 系统框架加载正常,但是Tomcat启动失败,报错如下: 2013-7-26 17:18:33 org.apache.catalina.core.StandardContext startInte ...
- 【32.26%】【codeforces 620C】Pearls in a Row
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- andriod 实现新浪、QQ场地、朋友微信圈、微信朋友分享功能
前言:在自己的学习过程中的一些操作,分享一些理解. 下面将说明什么: 下载链接:http://download.csdn.net/detail/u014608640/7490357 首先.我们须要去S ...
- node fs 文件/目录 删除
删除文件如下: 过程:先判断文件路径是否存在.读取该文件下所有文件.循环该文件,判断是否是文件夹还是文件. 移除文件夹使用fs.rmdirSync("路径") 移除文件使用fs.u ...
- 为什么台湾人工智能可能抢输大陆?(XPU时代来临)
到了 2020 年,每 3 支手机,就会有一支内建有 AI 芯片. 但目前浮出水面的 AI 芯片新创,几乎都是大陆公司. 为什么台湾这回选择缺席? 「我听说 CPU.GPU,没有听过 NPU? 」11 ...
- gdal1.10编译经验
作者:朱金灿 来源:http://blog.csdn.net/clever101 集成了一些扩展库,使用makefile编译,出现了一个链接错误: libcmt.lib(crt0.obj): erro ...