程序退出时意外终止和程序不能关掉(必须通过任务管理器关闭)的原因(续)
2011-12-26 14:52
351 查看
一、问题描述
描述:在上一篇中提到了CBioUSBAPI类存在bug使得程序退出后进行仍然驻留在内存中(后经验证,若注释掉CBioUSBAPI类的析构函数,则程序正常),必须通过任务管理器去强制关闭。
最近在制作两级对话框的时候又出现了与CBioUSBAPI类有关的错误问题:制作返回上一级对话框时界面卡死。后经验证,若注释掉CBioUSBAPI类的析构函数,则程序正常。
看来虽然两者错误的表象不一样,但问题的根源都出在了CBioUSBAPI类的构造函数上。
二、大胆猜测
猜测:从错误的表象来看,虽然一个是程序仍然驻留内存,一个界面关闭时卡死,但根源应该还是在于对话框退出时候其进程没有销毁。
三、发现问题
解决:最终发现问题出现在CBioUSBAPI类析构函数中调用了如下语句:
在此处设置断点发现while的判断语句始终为TRUE,导致程序停在了这里。这与前面的猜测基本吻合:即由于程序代码执行到这里就停止了,导致其进程无法关闭。
四、解决问题
这个while循环的意思应该是等待变量不为空,不管那么多了,先注释掉此句,发现先前存在的问题解决了。但在后面的关闭进程中又出现了异常:
First-chance exception at 0x7c92e4ff in RowDemo.exe: 0xC0000008: An invalid handle was specified.
Unhandled exception at 0x7c92e4ff in RowDemo.exe: 0xC0000008: An invalid handle was specified.
The thread 'Win32 Thread' (0x1308) has exited with code 0 (0x0).
通过设置断点找到出现异常抛出的位置在CloseHandle(hThread_IoControl);上
再通过watch窗口跟踪发现 hThread_IoControl变量值为0xcdcdcdcd,说明此变量是没有初始化的变量。因此要closeHandle去关闭一个没有初始化的句柄当然会报错。这里要注意的是变量没有初始化与变量为NULL(值为0x00000000)在vc中是两个不同的概念。
下面的试验也验证了这一点,如下调用是不会出现异常抛出错误的:
但是若hThread_IoControl=0xcdcdcdcd,则不行。
为什么会这样呢?主要是因为在vc中,在debug模式下,0xcdcdcdcd是当变量没有初始化时编译器默认的变量初始化值(0xcdcdcdcd是编译器默认的自动变量初始化值;编译器把所有未使用的内存都初始化成0xCD)。而NULL的值为0x00000000,这两个概念是不同的。因此当我们声明一个指针变量后,都要将NULL赋值给它,否则将会是野指针。
int * p; //没有初始化的野指针 。debug下在VC中值为0xcdcdcdcd
p = NULL; //这样才安全。值为0x00000000
//所以一般这么申明
int* p = NULL;
五、最后的代码
最后经证实,hThread_IoControl变量是我们的工程师先前创建一个读I/O线程时候开辟的,但他给我源代码的时候创建部分已经被它屏蔽了,但他却忘记把删除部分屏蔽了,结果就···
最后的正确代码应该是先在头文件中删除hThread_IoControl变量的声明,同时在析构函数中删除有关hThread_IoControl变量的代码,即while循环改成:
注释掉关闭hThread_IoControl线程句柄部分的代码:
六、总结
唉,看来养成一个良好的编程习惯比啥都重要哈
描述:在上一篇中提到了CBioUSBAPI类存在bug使得程序退出后进行仍然驻留在内存中(后经验证,若注释掉CBioUSBAPI类的析构函数,则程序正常),必须通过任务管理器去强制关闭。
最近在制作两级对话框的时候又出现了与CBioUSBAPI类有关的错误问题:制作返回上一级对话框时界面卡死。后经验证,若注释掉CBioUSBAPI类的析构函数,则程序正常。
看来虽然两者错误的表象不一样,但问题的根源都出在了CBioUSBAPI类的构造函数上。
二、大胆猜测
猜测:从错误的表象来看,虽然一个是程序仍然驻留内存,一个界面关闭时卡死,但根源应该还是在于对话框退出时候其进程没有销毁。
三、发现问题
解决:最终发现问题出现在CBioUSBAPI类析构函数中调用了如下语句:
// wait until the read/write and in/out thread destroyed while((hEvent_Read != NULL) || (hEvent_IoControl!=NULL));
在此处设置断点发现while的判断语句始终为TRUE,导致程序停在了这里。这与前面的猜测基本吻合:即由于程序代码执行到这里就停止了,导致其进程无法关闭。
四、解决问题
这个while循环的意思应该是等待变量不为空,不管那么多了,先注释掉此句,发现先前存在的问题解决了。但在后面的关闭进程中又出现了异常:
First-chance exception at 0x7c92e4ff in RowDemo.exe: 0xC0000008: An invalid handle was specified.
Unhandled exception at 0x7c92e4ff in RowDemo.exe: 0xC0000008: An invalid handle was specified.
The thread 'Win32 Thread' (0x1308) has exited with code 0 (0x0).
通过设置断点找到出现异常抛出的位置在CloseHandle(hThread_IoControl);上
if(hThread_IoControl != NULL) { CloseHandle(hThread_IoControl); //异常抛出的位置 hThread_IoControl = NULL; }
再通过watch窗口跟踪发现 hThread_IoControl变量值为0xcdcdcdcd,说明此变量是没有初始化的变量。因此要closeHandle去关闭一个没有初始化的句柄当然会报错。这里要注意的是变量没有初始化与变量为NULL(值为0x00000000)在vc中是两个不同的概念。
下面的试验也验证了这一点,如下调用是不会出现异常抛出错误的:
hThread_IoControl=NULL; //注意是NULL(0x00000000),而非0xcdcdcdcd closeHandle(hThread_IoControl)
但是若hThread_IoControl=0xcdcdcdcd,则不行。
为什么会这样呢?主要是因为在vc中,在debug模式下,0xcdcdcdcd是当变量没有初始化时编译器默认的变量初始化值(0xcdcdcdcd是编译器默认的自动变量初始化值;编译器把所有未使用的内存都初始化成0xCD)。而NULL的值为0x00000000,这两个概念是不同的。因此当我们声明一个指针变量后,都要将NULL赋值给它,否则将会是野指针。
int * p; //没有初始化的野指针 。debug下在VC中值为0xcdcdcdcd
p = NULL; //这样才安全。值为0x00000000
//所以一般这么申明
int* p = NULL;
五、最后的代码
最后经证实,hThread_IoControl变量是我们的工程师先前创建一个读I/O线程时候开辟的,但他给我源代码的时候创建部分已经被它屏蔽了,但他却忘记把删除部分屏蔽了,结果就···
hThread_IoControl = (HANDLE)CreateThread(NULL, 0, ThreadExecute_IoControl, this, 0, &dwThreadID_IoControl);
最后的正确代码应该是先在头文件中删除hThread_IoControl变量的声明,同时在析构函数中删除有关hThread_IoControl变量的代码,即while循环改成:
while((hEvent_Read != NULL));
注释掉关闭hThread_IoControl线程句柄部分的代码:
//if(hThread_IoControl != NULL) // { // CloseHandle(hThread_IoControl); // hThread_IoControl = NULL; // }
六、总结
唉,看来养成一个良好的编程习惯比啥都重要哈
相关文章推荐
- 程序退出时意外终止和程序不能关掉(必须通过任务管理器关闭)的原因
- pb中调用API函数后程序莫名关闭退出原因之一
- 通过文件锁实现,程序开始运行时,先判断文件是否存在,若存在则表明该程序已经在运行了,如果不存在就用open函数创建该文件,程序退出时关闭文件并删除文件。
- Windows关闭程序托盘图标不能消失的原因
- 启动tomcat失败,原因端口占用,但是不能通过结束服务关掉tomcat解决方法
- 【转】通过文件锁实现,程序开始运行时,先判断文件是否存在,若存在则表明该程序已经在运行了,如果不存在就用open函数创建该文件,程序退出时关闭文件并删除文件
- JQuery Dialog对话框 不能通过Esc关闭的原因分析及解决办法
- MFC中通过子窗口关闭父窗口以实现退出程序
- 通过windug判断某个模块导致程序不能退出。
- 关于程序退出无法关闭所有界面问题 通过广播使Android程序完全退出
- Linux+QT+OpenCv摄像头调试心得(2)----点击退出关闭窗体,提示“程序异常终止”
- 通过文件锁实现,程序开始运行时,先判断文件是否存在,若存在则表明该程序已经在运行了,如果不存在就用open函数创建该文件,程序退出时关闭文件并删除文件
- 玩魔兽争霸无故退出 提示框显示"0x21101663"指令引用的"0x02704acc"内存该存不能为"read" 确定就会终止程序
- 需求:需要在许多子窗体中关闭/退出整个程序(WPF)
- android程序退出关闭多个activity
- 解决虚拟键盘关闭后无法退出程序的问题
- 【Android】【转】Android程序退出彻底关闭进程的方法
- 【代码】Android和java平台 DES加密解密互通程序及其不能互通的原因
- 中断处理程序中不能出现睡眠代码的原因
- MFC MDI程序的退出菜单突然不能退出了