应用程序退出时,临界区回收出错导致的进程异常
来源:互联网 发布:基因比对软件 编辑:程序博客网 时间:2024/05/22 07:44
应用程序退出时,临界区回收出错导致的进程异常。
问题看起来不是很严重,因为异常仅仅发生在应用程序退出时,此时,即使程序崩溃也没有什么太大的影响。类似问题以前也遇到过,当时由于代码量太多,所以,直接pass。
异常中断时,函数调用栈如下:
> XX.exe!AfxCriticalTerm() 行 62C++
XX.exe!_AfxTermAppState() 行 60C++
XX.exe!doexit(int code=0x00000002, int quick=0x00000000, int retcaller=0x00000000) 行 567C
XX.exe!exit(int code=0x00000002) 行 393 + 0xd 字节C
XX.exe!__tmainCRTStartup() 行 284C
XX.exe!wWinMainCRTStartup() 行 189C
异常的函数调用:(afxcrit.cpp)
void AFXAPI AfxCriticalTerm()
{
if (_afxCriticalInit)
{
VERIFY(!--_afxCriticalInit);
// delete helper critical sections
DeleteCriticalSection(&_afxLockInitLock);
// delete specific resource critical sections
for (int i = 0; i < CRIT_MAX; i++)
{
#ifdef _DEBUG
ASSERT(!_afxResourceLocked[i]);
#endif
if (_afxLockInit[i])
{
DeleteCriticalSection(&_afxResourceLock[i]); //中断
VERIFY(!--_afxLockInit[i]);
}
}
}
}
程序代码:
//类声明
class CBTUpdate
{
public:
CBTUpdate(void);
~CBTUpdate(void);
_DefineClassVariableReference(UINT, CurrentVersion);
_DefineClassVariableReference(FILE_LIST, Files);
_DefineClassVariableReference(CTL_CriticalSection, Lock); //临界区
_DefineClassVariableReference(BOOL, IsUpdating);
public:
int Load();
int Save();
};
//类实现
CBTUpdate::CBTUpdate(void)
{
m_IsUpdating=FALSE;
}
CBTUpdate::~CBTUpdate(void)
{
}
int CBTUpdate::Load()
{
return 0;
}
int CBTUpdate::Save()
{
return 0;
}
其中,_DefineClassVariableReference是一个宏。因为VC的变量定义很麻烦,一个标准的VC代码定义,应该有一个Get方法和Set方法,然而VC向导没有这样的功能。如果每个变量定义都自己写,那么,上面的四个变量定义,就得近40行代码。所以,改用宏定义的方式,4行代码解决。
应用程序退出时,调用CBTUpdate::~CBTUpdate()析构函数,随后出现异常。
根据以上信息,基本上可以确定,由于回收临界区出现问题,导致进程异常!
于是,我根据这些结论,找出问题代码:
CBTUpdate a;
CBTUpdate b;
b=a; //问题代码
是赋值函数出了问题!这时候才恍然大悟。VC 2010和VC6不同,它会给类和结构体加上默认的赋值运算,上面的类,等同于存在这样一个缺省的赋值运算符重载函数:
CBTUpdate & CBTUpdate::operator=(const CBTUpdate & r)
{
m_CurrentVersion=r.m_CurrentVersion;
m_Files=r.m_Files;
m_IsUpdating=r.m_IsUpdating;
m_Lock=r.m_Lock;
return *this;
}
可以看到,倒霉的事情发生在m_Lock=r.m_Lock;,临界区变量被赋值函数给覆盖了!于是,析构的时候,a析构一次a.m_Lock临界区变量,b也会析构一次b.m_Lock,两次析构就调用两次DeleteCriticalSection函数,同一个临界区被DeleteCriticalSection两次,自然也就发生异常了!
至此,原因找到。解决方法是重载赋值运算符函数,如下:
CBTUpdate & CBTUpdate::operator=(const CBTUpdate & r)
{
m_CurrentVersion=r.m_CurrentVersion;
m_Files=r.m_Files;
m_IsUpdating=r.m_IsUpdating;
return *this;
}
By:zhanyonhu#@#163.com
- 应用程序退出时,临界区回收出错导致的进程异常
- 进程异常退出导致死锁的解决办法
- Visual Studio 2008的Vmware插件导致Visual Studio编译出错并异常退出的问题
- .NET Framework 2.0 中未处理的异常导致基于 ASP.NET 的应用程序意外退出
- linux 进程的创建 和退出回收
- 项目中异常退出导致的问题。
- backtrace-----打印进程异常退出时的堆栈信息
- backtrace-----打印进程异常退出时的堆栈信息
- 父进程异常退出时,确保子进程退出
- 解决openoffice进程异常退出的办法
- 退出应用程序杀死进程
- IIS应用程序池回收导致SignalR链接断开的解决办法
- 浅谈进程非正常退出时资源回收相关的函数pthread_cleanup_push/pthread_cleanup_pop
- 解决进程间共享内存,由于某个进程异常退出导致死锁问题
- 进程PCB、临界区
- 线程、进程、临界区
- send 函数导致进程退出
- SIGPIPE信号导致进程退出
- 一位成功的科学家是能发现最有价值问题的探索者
- myeclipse8.6下freemarker编辑器---freemarker-ide的安装
- win32 sdk中ListView列表控件的使用
- alter system set events
- 临界区:多线程同步
- 应用程序退出时,临界区回收出错导致的进程异常
- 主线程与用户界面线程(含有消息泵的线程)的通信
- MFC上的多线程编程
- Android模拟器学framework和driver之传感器篇2(生成测试tool)
- Gentoo Linux安装注意事项
- 了解WaitForSingleObject
- <vector> template实现
- CreateEvent和SetEvent及WaitForSingleObject的用法
- WaitForSingleObject和WaitForMultipleObjects用法