假设:
有dll my_dll
CWinAppDll{
InitInstance(){
m_socket.Socket(SOCK_DGRAM); //这几个可选参数,导致套接字为异步模式,并且启用了WSAAsyncSelect通知}
CSocket m_socket;
}
export function DoSomeThing(){
//设置模块状态,懒的写
m_socket.xxx //比如这里对套接字进行操作
}
有exe my_exe,并且引用了my_dll
{
UI Handler(){
//比如某个动作,调用到my_dll的某个功能
}
}
在my_exe退出的时候,将要析构CWinAppDll,先析构他的成员m_socket,将调用到CSocket::Close,这里有一个WSAAsyncSelect(0); 他将事件通知和SOCKWND分离,这个函数注定调用是失败的,因为在析构CWinAppDll的时候,你的my_dll已经Detach,并且其他的DLL很可能已经Detach,特别是WINSOCK的DLL,这个DETACH顺序不清楚,但是可以肯定WINSOCK已经Detach了,因为在析构CWinAppDll的时候,无论你在调用WINSOK相关的函数都失败,LastError=10093.
WSAAsyncSelect(0)之后是真正的closesocket,这个函数也会失败,因为WINSOCK已经Detach了.这样你的程序就有句柄和内存泄漏.
所以,不要偷懒用这种方式来在DLL内自动关闭套接字句柄.应该在应用程序退出之前显示的告诉DLL关闭句柄.
进程内全局的也一样会有这种问题.(原因很多,对于MFC最多可能是模块卸载了,模块环境没有了)