經典 VC6.0 MFC 應用通過 ODBC 連接 SQL Server 2005,運行一段時間後 CRecordset::Open() 拋出「內存不足」異常,且僅能寫入一條記錄。最終通過重建數據庫解決,但根因未定論。本文復盤排查路徑,提供可復用的自查清單。
CRecordSet m_useBLOB; // 派生自 CRecordset
try {
m_useBLOB.Open(); // 斷點處直接跳 catch
// ...
} catch (CException* pE) {
pE->ReportError(); // 提示「內存不足」
pE->Delete();
}
| 疑點 | 驗證方法 | 典型徵兆 |
|---|---|---|
| ODBC 驅動/客戶端內存洩漏 | 換用 SQL Server Native Client 10.0 或更高版驅動;啟用 ODBC 追蹤日志 | 驅動版本舊(2005 早期版)、長連接不斷增長 |
| CRecordset 未正確關閉 | 檢查所有分支是否調用 Close();析構函數中兜底關閉 | 異常拋出路徑漏調 Close、事務未提交/回滾 |
| BLOB/CLOB 字段處理不當 | 改用 CLongBinary 或 CLongBinary::GetData() 分塊讀寫 | 表含 image/text/ntext 類型、單條數據 > 1MB |
| 連接池/會話泄漏 | ODBC 管理器查看活動連接數;代碼確保 CDatabase::Close() 配對 | 連接數隨時間單調遞增、達到最大連接數 |
| SQL Server 內存配置/碎片 | SSMS 查看 target server memory、DBCC MEMORYSTATUS;重建數據庫/重建索引 | 重建數據庫後症狀消失(本案實測有效) |
| VC6 運行時庫/堆損壞 | 改用 /MD 動態鏈接 CRT;啟用 _CrtSetDbgFlag 檢測堆完整性 | Debug 模式下斷點觸發 _CrtIsValidHeapPointer 失敗 |
OLE DB Services 或自建連接池,隔離 ODBC 狀態。SELECT 1 探活,失敗時重建連接對象。若仍需維護舊系統,建議在啟動時強制設置 SetProcessWorkingSetSize(GetCurrentProcess(), -1, -1) 釋放工作集,緩解虛擬地址空間碎片(32 位進程 2GB 限制下常見緩解手段)。