1. dll内部创建的thread , 在 dll被freelibrary 后, thread 是不是继续存在?
但是, thread 内部如果这时候调用 dll 的资源(比如字符串资源如: MessageBox( ..., L"Hello world" , ... ) ) 可能造成crash?
2. 如果thread 能够继续存在, 那么代码块为什么没有被回收?3. 我看过exe的 Load 和 Unload , 但是现在还想看, 有没有人有这篇文章? 另外,有没有 dll 的这类相关文章.4. 我在我的dll中 开启了一个 udp recvfrom 线程 , 但是遇到奇怪问题.
代码如下:
dll全局类的析构函数
CAttach::~CAttach()
{
::closesocket( _skRecvCommand ) ;
::WaitForSingleObject( _hListenCommandInfo , INFINITE ) ; // 在这里会造成假死
// 如果不WaitForSingleObject , 跟踪程序发现,在~Attach()后,thread 会正常退出.
::CloseHandle( _hListenCommandInfo ) ; ShowString(L"end");
}
同时thread:
DWORD
CAttach::_ListenCommandInfo( PVOID pArg )
{
...........
bool bContinue = true ;
while( bContinue )
{
int nRet = ::recvfrom(_skRecvCommand, (PSTR)&stCommand, sizeof(COMMANDINFO), 0, (SOCKADDR *)&_stRecvAddr , &SenderAddrSize);
if( nRet == 0 || nRet == SOCKET_ERROR )
break ;
}
// ShowString(L"hello world"); //这句会使 exe crash
return 0 ;
}请大家看看.谢谢
但是, thread 内部如果这时候调用 dll 的资源(比如字符串资源如: MessageBox( ..., L"Hello world" , ... ) ) 可能造成crash?
2. 如果thread 能够继续存在, 那么代码块为什么没有被回收?3. 我看过exe的 Load 和 Unload , 但是现在还想看, 有没有人有这篇文章? 另外,有没有 dll 的这类相关文章.4. 我在我的dll中 开启了一个 udp recvfrom 线程 , 但是遇到奇怪问题.
代码如下:
dll全局类的析构函数
CAttach::~CAttach()
{
::closesocket( _skRecvCommand ) ;
::WaitForSingleObject( _hListenCommandInfo , INFINITE ) ; // 在这里会造成假死
// 如果不WaitForSingleObject , 跟踪程序发现,在~Attach()后,thread 会正常退出.
::CloseHandle( _hListenCommandInfo ) ; ShowString(L"end");
}
同时thread:
DWORD
CAttach::_ListenCommandInfo( PVOID pArg )
{
...........
bool bContinue = true ;
while( bContinue )
{
int nRet = ::recvfrom(_skRecvCommand, (PSTR)&stCommand, sizeof(COMMANDINFO), 0, (SOCKADDR *)&_stRecvAddr , &SenderAddrSize);
if( nRet == 0 || nRet == SOCKET_ERROR )
break ;
}
// ShowString(L"hello world"); //这句会使 exe crash
return 0 ;
}请大家看看.谢谢
_hListenCommandInfo 是Thread的句柄.第4个问题我没说清楚: 如果我在~CAttach()中等待 _ListenCommandInfo 结束, 就会假死, 好像这个线程永远不结束. 但是如果我不等待, 我发现线程会在 ~CAttach()之后结束.就是这个问题.
因为DLL其实跟EXE在本质上没多大区别。只不过运行,卸载,以及被调用的方式有些不同而已。
EXE关闭的时候所有关于这个EXE的东西都会被系统回收,哪怕是泄露掉的内存。
这样来看,这个线程应该是被杀掉了。
2、伪命题,只有一个解释,那就是DLL的引用计数不为0,没有卸载
3、NONE
4、WaitForSingleObject不要放在全局对象的析构函数中调用,容易造成死锁,DLL的全局对象构造和析构时需要万分小心,很多功能都不能使用。通常把这种敏感的清理放在一个导出函数里,由应用程序调用,或者使用类似于引用计数的方式自动清理。
如果某个DLL已经被卸载,而某个线程又要访问该DLL(包括执行代码或者访问数据),则在访问时会产生异常。
再举个例子:假设在DLL中写了一个线程函数,函数中执行MessageBox,在显示MessageBox期间DLL被卸载,在卸载DLL时不会发生问题,但如果关闭MessageBox,则会产生异常。因为执行MessageBox期间不需要访问DLL,而从MessageBox返回后还要执行DLL中的代码,而此时DLL的代码已经被释放掉了,所以会产生异常。
我曾遇到过一个问题。自己的动态库中,在开始的时候调用一个接口来产生一个句柄,然后其它的接口中都需要传入这个句柄,包括销毁接口。在调试的时候,其它接口都正常,就是销毁接口不正常,挂掉,经跟踪发现,当进入到销毁接口中时,所有的变量全部变成了无效。后来才发现,是因为上层把动态库从内存中清除掉了,所以一切都无效了。由以上我的问题可以知道,如果动态库被freelibrary了,则它里面的线程,包括任何形式的变量,会全部无效,包括你去获取动态库中的资源,因为这个动态库已经没有在内存中了,所以,它里面的任何东西都不可能存在!