std::string一个极其隐晦得问题

std::string一个极其隐晦得问题

昨天做一个dll,代码很快写完了,然而使用得时候总是遇到string内部指针删除错误,郁闷了一天,今天没去公司,好好研究了一下。
首先看下下面这段代码,声明两个string对象:

std:: string   s1  =   " wlwlxj " ;
std::
string   s2  =   " lxjwlwww " ;

调试状态下可以看到内部指针:
s1=0x00364ff9
s2=0x00365061
然后执行

s2  =  s1;

按下f11,进入xstring源文件:

_Myt &   operator = ( const  _Myt &  _X)         // 赋值操作符
  
{ return  (assign(_X)); }                     // 调用assign函数

继续进入assign(_X)函数:

_Myt &  assign( const  _Myt &  _X)
        
{ return  (assign(_X,  0 , npos)); }   // 调用assign函数
继续进入assign函数,好戏都在这里面:
_Myt &  assign( const  _Myt &  _X, size_type _P, size_type _M)
        
{if (_X.size() < _P)
            _Xran();
        size_type _N 
= _X.size() - _P;
        
if (_M < _N)
            _N 
= _M;
        
if (this == &_X)
            erase((size_type)(_P 
+ _N)), erase(0, _P);
        
else if (0 < _N && _N == _X.size()                        // 这个分支意思就是如果拷贝源有内容且就是就是源本身,并且
            
&& _Refcnt(_X.c_str()) < _FROZEN - 1          // 源字符串引用次数少于255-1次(可见引用次数最多255次),
            
&& allocator == _X.allocator)                           //且源字符和目的字符分配器一致
            
{_Tidy(true);                                             // 删除本身
            _Ptr 
= (_E *)_X.c_str();                                    // 复制内容到目的串
            _Len 
= _X.size();
            _Res 
= _X.capacity();
            
++_Refcnt(_Ptr); }                                             // 增加一次引用

        
else if (_Grow(_N, true))
            
{_Tr::copy(_Ptr, &_X.c_str()[_P], _N);
            _Eos(_N); }

        
return (*this); }

这样结果就是调用=号以后,s2地址和s1地址一样,都是0x00364ff9。

假如我们动态库有这样一个类class DLL接口:

SetString(std:: string  str)
{
m_str 
= str;
}

在客户调用时候:

std:: string  str  =   " wlwlxj " ;
DLL d;
d.SetString(str); 
//  此时没有深拷贝,而是引用了str内部指针地址
在调用结束的时候,dll内部删除成员变量的时候,会判断m_str内部指针合法性,由于实际分配是在调用端,在dll内部自然检查指针非法。

解决方法就是避免std::string引用计数,接口处修改为SetString(const char*),这样在dll内部分配内存,内部释放,就不会有问题。

你可能感兴趣的:(std::string一个极其隐晦得问题)