vc++ 6.0标准库string类的bug

vc++ 6.0标准库string类的bug

许式伟
2006-12-23

 

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语句上。你的数组被理解为是一个'/0'结尾的“字符串”。这样_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

问题在于: 

  1. 既然它是标准库,直接修改它的代码并不是很好,因为你的同事(或者其他人)还在用着有问题的版本。
     
  2. 如果你采用MultiThread DLL模式链接C++标准库,这意味着就算你修改了vc++的头文件也没用,因为编译器最终链接的是dll中的代码,而不是你修改后的代码。

怎么办呢?

winx就这个问题进行了一定程度的修复(参见最新的发布包)。也就是说,只要你包含了最新的winx,多数情况下不会出现此bug。但如果你采用MultiThread DLL模式链接C++标准库(问题挺严重,因为这是推荐的链接方式),那么你需要小心使用string、wstring类(但是其他类诸如basic_string<double>没问题),因为此模式下winx并没有修复该bug。注意不要让字符串中出现'/0'字符即可。如果确实需要出现'/0'的字符串,可使用winx::CString类。 

点击以下链接下载最新的WINX:

 

转载于:https://www.cnblogs.com/wuwuwu/archive/2006/12/23/6162456.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值