客戶端點擊「獲取屏幕」即彈出 Out of Memory,且無法定位具體代碼行。
CreateCompatibleBitmap/CreateCompatibleDC 後未 DeleteObject/DeleteDC,導致 GDI 對象計數飆升(上限 10k/進程),觸發分配失敗並誤報「內存不足」。send 非阻塞模式下數據在應用層隊列無限增長。// 在可疑函數入口/出口插入
TRACE(_T(">>> Enter CaptureScreen, GDI Count=%d\n"), GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS));
try {
// 原邏輯
} catch (CMemoryException* e) {
AfxMessageBox(_T("CMemoryException caught!"));
e->Delete();
}
TRACE(_T("<<< Leave CaptureScreen, GDI Count=%d\n"), GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS));
觀察輸出窗口 GDI 計數變化,鎖定泄漏函數。
| 問題 | 修復 |
|---|---|
| 位圖過大 | 抓取前按比例縮放(如 50%),或直接用 StretchBlt 繪制到較小 DC;採用 JPEG/PNG 壓縮(GDI+ / libjpeg-turbo)再發送。 |
| GDI 泄漏 | 嚴格遵循 誰創建誰釋放,用 CBitmap/CDC 等 MFC 封裝類利用 RAII 自動釋放。 |
| 發送堆積 | 發送端引入背壓機制:發送隊列達高水位暫停抓屏;或改用 UDP + FEC 容忍丟包。 |
| 32位地址空間耗盡 | 編譯為 x64 Release,虛擬地址空間 128 TB,徹底解決大內存分配失敗。 |
!address -summary (WinDbg) 查看堆碎片。