首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

VC++ 6.0 STL string 類別 Copy-on-Write Bug 分析與修復

     編輯:VC 教學

背景:basic_string 作為泛型動態陣列

std::basic_string<T> 不限於字元,可作為任意型別 T 的動態陣列 (如 basic_string<double>)。優勢在於 Copy-on-Write (COW):賦值僅增引用計數 (AddRef),極快;std::vector 則需完整記憶體拷貝。此特性對矩陣運算 (Matrix = a; Matrix += b;) 效能提升顯著。

Bug 發現:_Split 中的字串化假設

VC6 STL basic_string::_Split() 實作:

void _Split() {
    if (_Ptr != 0 && _Refcnt(_Ptr) != 0 && _Refcnt(_Ptr) != _FROZEN) {
        _E* _Temp = _Ptr;
        _Tidy(true);
        assign(_Temp); // 錯誤:視為以 '\0' 結尾的字串
    }
}

當 T != char (如 double) 且陣列元素含 0 時,assign(_Temp) 會在第一個 0 處截斷,導致資料遺失。

修復代碼

修改 xstring 標頭檔中 _Split 實作:

void _Split() {
    if (_Ptr != 0 && _Refcnt(_Ptr) != 0 && _Refcnt(_Ptr) != _FROZEN) {
        _E* _Temp = _Ptr;
        size_type _N = _Len;        // 保存原始長度
        _Tidy(true);
        assign(_Temp, _N);          // 指定長度,避免 '\0' 截斷
    }
}

部署難題與替代方案

  • 直接修改標頭檔:僅影響原始碼層級,若連結 Multi-threaded DLL (/MD),實際執行的是 msvcprt.dll 內未修復代碼,**無效**。
  • WinX 庫修復:包含最新 WinX 標頭可修復靜態連結情況,但 /MD 下 string/wstring 仍受 DLL 版本影響。
  • 建議:
    1. 優先使用 靜態連結 CRT (/MT) 並修改標頭檔。
    2. 避免在 string/wstring 中存放 '\0' 字元。
    3. 需存放二進位資料或含 0 元素的非字元陣列,請改用 std::vector 或 winx::CString (非 MFC CString)。

結論

VC6 STL COW 實作假設字串語意,導致泛型陣列用法失效。升級至 VS2005+ (放棄 COW、採用 SSO) 為根本解決;維護舊專案請謹慎評估連結模式與資料特性。

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