程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> vc教程 >> vc++ 6.0標准庫string類的bug

vc++ 6.0標准庫string類的bug

編輯:vc教程

basic_string類的用途
basic_string並不象它的名字那樣,只可能是一個字符串。有時候,它不那麼象字符串。例如:

typedef std::basic_string<double> DoubleArray;
此時,basic_string是一個double類型的動態數組。你可能說,為什麼不用vector呢?如下:

typedef std::vector<double> DoubleArray;
這兩者有什麼不同?其實最大的不同,在於basic_string類通常是基於copy-on-write技術的。這意味著basic_string的賦值操作(Operator=)只是一個簡單的加引用計數(AddRef),是相當快速的。而vector類的賦值操作則是真正的內存拷貝過程。

現在我要實現一個矩陣(Matrix)類。你可以想象一下現在要矩陣的各種運算,例如加法(Operator+):

Matrix Operator+(const Matrix& a, const Matrix& b)
{
    Matrix result = a;
    result += b;
    return result;
}
你可以發現,如果Matrix內部采用vector,而不是用basic_string,那麼Matrix類的Operator+中就有多次無謂的內存拷貝過程。

bug的發現
我的Matrix類一直工作的很好,直到有一天,我發現某個Matrix的數據少了。跟蹤發現,問題出在basic_string的copy-on-write實現上。vc++ 6.0的stl中,basic_string通過_Split函數進行分裂:

class basic_string {
    void _Split()
        {if (_Ptr != 0 && _Refcnt(_Ptr) != 0 && _Refcnt(_Ptr) != _FROZEN)
            {_E *_Temp = _Ptr;
            _Tidy(true);
            assign(_Temp); }}
};
問題出在上面的assign語句上。你的數組被理解為是一個''結尾的“字符串”。這樣_Split操作完成後,如果某個數組元素為0,數據變少了。

bug的修復
找到了肇事者,修改代碼還是很容易,如下:

    void _Split()
        {if (_Ptr != 0 && _Refcnt(_Ptr) != 0 && _Refcnt(_Ptr) != _FROZEN)
            {_E *_Temp = _Ptr;
             size_type _N = _Len;
            _Tidy(true);
            assign(_Temp, _N); }} //@@code modify: assign(_Temp); ---> bug fixed by xushiwei
問題在於:

既然它是標准庫,直接修改它的代碼並不是很好,因為你的同事(或者其他人)還在用著有問題的版本。
 
如果你采用MultiThread DLL模式鏈接C++標准庫,這意味著就算你修改了vc++的頭文件也沒用,因為編譯器最終鏈接的是dll中的代碼,而不是你修改後的代碼。
怎麼辦呢?

winx就這個問題進行了一定程度的修復(參見最新的發布包)。也就是說,只要你包含了最新的winx,多數情況下不會出現此bug。但如果你采用MultiThread DLL模式鏈接C++標准庫(問題挺嚴重,因為這是推薦的鏈接方式),那麼你需要小心使用string、wstring類(但是其他類諸如basic_string<double>沒問題),因為此模式下winx並沒有修復該bug。注意不要讓字符串中出現''字符即可。如果確實需要出現''的字符串,可使用winx::CString類。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved