首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Visual C++ char 數組溢出:DLL 寫入超過主程序預期長度導致崩潰

     編輯:程式設計疑難解答

現象

  • 主程序 char Msg[1024],調用 DLL check(Msg)。
  • DLL 中 strcpy/strcat 拼接字符串。
  • 實際寫入 ≤ 512 字節正常,> 512 字節主程序 AddString 時崩潰。

根因分析

  1. 緩衝區實際大小非 1024:雖然聲明 char Msg[1024],但可能被編譯器優化、對齊、或被其他代碼覆蓋了前 512 字節後的內存保護標記(如 /GS Buffer Security Check 插入的 Cookie)。
  2. DLL 與主程序 CRT 版本不一致:動態鏈接 CRT 時,雙方各自維護堆/檢查機制,跨 DLL 邊界傳遞裸指針操作內存極其危險。
  3. 無邊界檢查的 strcat:代碼片段中 strcat(msg, "buff") 完全不檢查剩餘空間,極易溢出。

修復方案(按推薦度)

1. 改用安全字符串函數 + 顯式傳遞長度


// DLL 導出
extern "C" __declspec(dllexport) int check(char* msg, size_t maxLen) {
    if (!msg || maxLen == 0) return -1;
    msg[0] = '\0';
    char buf[256];
    int len = 0;
    // 每次拼接檢查剩餘空間
    auto append = [&](const char* fmt, ...) {
        if (len >= maxLen - 1) return;
        va_list args;
        va_start(args, fmt);
        int n = _vsnprintf_s(buf, sizeof(buf), _TRUNCATE, fmt, args);
        va_end(args);
        if (n > 0 && len + n < maxLen) {
            strcpy_s(msg + len, maxLen - len, buf);
            len += n;
        }
    };
    append("xxxxxx%d,%d", int1, int2);
    append("xxxxxx%d,%d", int3, int4);
    // ...
    return 0;
}

// 主程序調用
char Msg[1024];
check(Msg, sizeof(Msg));

2. 統一 CRT:專案屬性 → C/C++ → Code Generation → Runtime Library 選 **MD/MDd** (動態共享),所有 DLL/EXE 一致。

3. 採用 CString / std::string 內部管理內存,導出介面傳 BSTR 或 const char* (只讀),由調用方負責複製。

調試定位具體崩潰點

  • 開啟 /GS (Buffer Security Check) —— 默認開啟。
  • 運行 Debug 版,崩潰時調用堆疊會指向 **檢測到緩衝區覆蓋** 的具體位置(通常在函數尾聲 __security_check_cookie)。
  • 啟用 Application Verifier + Basics → Heaps,捕捉跨 DLL 內存越界。

裸指針跨 DLL 操作字符數組是 C++ 經典雷區,**顯式長度 + 安全函數 + 統一 CRT** 三管齊下才安心!

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved