自己写了个DLL连接数据库,EXE程序调用出现Crash有关问题.请问
自己写了个DLL连接数据库,EXE程序调用出现Crash问题.请教?
自己写了个DLL连接数据库.当调用这个DLL的EXE退出的时候,就出现Crash.Crash的地方是:
//c:\program files\microsoft visual studio 8\vc\include\comip.h
void _Release() throw()
{
if (m_pInterface != NULL) {
m_pInterface-> Release(); //Crash
}
}
如果我把DLL中的代码放在Application中,即不用DLL,就没有问题.
我现在分离出了最小的代码集.可能还是有点长.
DLL的入口是一个CDataCenter类,它的静态方法调用一个实现了单态模式的类CADOManager,CADOManager类中包含一个成员变量_ConnectionPtr m_pCon;连接和关闭数据库就是调用m_pCon的方法.
///////////////DataAccess.DLL
//class CADOManager
//ADOManager.h
class CADOManager
{
friend CADOManager* TheADOManager();
public:
CADOManager(void);
public:
~CADOManager(void);
BOOL Inital();
BOOL ExInital();
private:
_ConnectionPtr m_pCon;
static auto_ptr <CADOManager> m_instance;
};
CADOManager* TheADOManager();
//ADOManager.cpp
auto_ptr <CADOManager> CADOManager::m_instance;
CADOManager::CADOManager(void)
{
}
CADOManager::~CADOManager(void)
{
}
BOOL CADOManager::Inital()
{
m_pCon.CreateInstance(__uuidof(Connection));
m_pCon-> Open(_bstr_t(_T( "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\\sss.xls;Extended Properties=\ "Excel 8.0;HDR=Yes\ "; ")),_bstr_t(_T( " ")),_bstr_t(_T( " ")),adModeUnknown);
return TRUE;
}
BOOL CADOManager::ExInital()
{
m_pCon-> Close();
return TRUE;
}
CADOManager* TheADOManager()
{
if(0 == CADOManager::m_instance.get())
{
CADOManager::m_instance.reset(new CADOManager);
}
return CADOManager::m_instance.get();
}
//class CDataCenter
//DataCenter.h
class __declspec(dllexport) CDataCenter
{
public:
static BOOL Inital();
static BOOL ExInital();
};
//DataCenter.cpp
BOOL CDataCenter::Inital()
{
TheADOManager()-> Inital();
return TRUE;
}
BOOL CDataCenter::ExInital()
{
TheADOManager()-> ExInital();
return TRUE;
}
////////////////////////Appliaction
//Code:
CDataCenter::Inital();
CDataCenter::ExInital();
------解决方案--------------------
检查一下你的CoUninitialize, 是不是在Release之前就被Call了。
用Smart Pointer的时候一定要小心全局变量,你这里 auto_ptr <CADOManager> CADOManager::m_instance; 要在CoUninitialize之前 (或者OleUninitialize)把所有的Release都弄干净,否则你的COM Apartment一丢,再Release就Crash了。
------解决方案--------------------
千万不要用catch(...)!
这是很多公司最后花无数多钱请专家的一个重要原因。C++的catch(...)会抓住Structure Exception, 这样就把一些比如Access Denied等致命的错误都抓住了,还有比如Heap Corruption,最后出错的时候已经无法跟踪解决了。这个catch(...)是 C++ 里设计很糟糕的一个东西。
楼主程序之所以Crash就是因为用了智能指针,因为是全局变量,所以在Main 函数结束以后Release才被自动叫到。这个时候通常COM 已经都结构了(CoUninitialze被叫过了),所以会立即Crash。这个根本不是 COM 的 exception, _com_error根本抓不到。
自己写了个DLL连接数据库.当调用这个DLL的EXE退出的时候,就出现Crash.Crash的地方是:
//c:\program files\microsoft visual studio 8\vc\include\comip.h
void _Release() throw()
{
if (m_pInterface != NULL) {
m_pInterface-> Release(); //Crash
}
}
如果我把DLL中的代码放在Application中,即不用DLL,就没有问题.
我现在分离出了最小的代码集.可能还是有点长.
DLL的入口是一个CDataCenter类,它的静态方法调用一个实现了单态模式的类CADOManager,CADOManager类中包含一个成员变量_ConnectionPtr m_pCon;连接和关闭数据库就是调用m_pCon的方法.
///////////////DataAccess.DLL
//class CADOManager
//ADOManager.h
class CADOManager
{
friend CADOManager* TheADOManager();
public:
CADOManager(void);
public:
~CADOManager(void);
BOOL Inital();
BOOL ExInital();
private:
_ConnectionPtr m_pCon;
static auto_ptr <CADOManager> m_instance;
};
CADOManager* TheADOManager();
//ADOManager.cpp
auto_ptr <CADOManager> CADOManager::m_instance;
CADOManager::CADOManager(void)
{
}
CADOManager::~CADOManager(void)
{
}
BOOL CADOManager::Inital()
{
m_pCon.CreateInstance(__uuidof(Connection));
m_pCon-> Open(_bstr_t(_T( "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\\sss.xls;Extended Properties=\ "Excel 8.0;HDR=Yes\ "; ")),_bstr_t(_T( " ")),_bstr_t(_T( " ")),adModeUnknown);
return TRUE;
}
BOOL CADOManager::ExInital()
{
m_pCon-> Close();
return TRUE;
}
CADOManager* TheADOManager()
{
if(0 == CADOManager::m_instance.get())
{
CADOManager::m_instance.reset(new CADOManager);
}
return CADOManager::m_instance.get();
}
//class CDataCenter
//DataCenter.h
class __declspec(dllexport) CDataCenter
{
public:
static BOOL Inital();
static BOOL ExInital();
};
//DataCenter.cpp
BOOL CDataCenter::Inital()
{
TheADOManager()-> Inital();
return TRUE;
}
BOOL CDataCenter::ExInital()
{
TheADOManager()-> ExInital();
return TRUE;
}
////////////////////////Appliaction
//Code:
CDataCenter::Inital();
CDataCenter::ExInital();
------解决方案--------------------
检查一下你的CoUninitialize, 是不是在Release之前就被Call了。
用Smart Pointer的时候一定要小心全局变量,你这里 auto_ptr <CADOManager> CADOManager::m_instance; 要在CoUninitialize之前 (或者OleUninitialize)把所有的Release都弄干净,否则你的COM Apartment一丢,再Release就Crash了。
------解决方案--------------------
千万不要用catch(...)!
这是很多公司最后花无数多钱请专家的一个重要原因。C++的catch(...)会抓住Structure Exception, 这样就把一些比如Access Denied等致命的错误都抓住了,还有比如Heap Corruption,最后出错的时候已经无法跟踪解决了。这个catch(...)是 C++ 里设计很糟糕的一个东西。
楼主程序之所以Crash就是因为用了智能指针,因为是全局变量,所以在Main 函数结束以后Release才被自动叫到。这个时候通常COM 已经都结构了(CoUninitialze被叫过了),所以会立即Crash。这个根本不是 COM 的 exception, _com_error根本抓不到。