昨天做一个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函数
_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内部指针地址
解决方法就是避免std::string引用计数,接口处修改为SetString(const char*),这样在dll内部分配内存,内部释放,就不会有问题。
本文探讨了std::string在不同模块(如DLL与EXE)间传递时引发的内部指针删除错误问题。通过深入分析std::string的赋值操作符及内部实现,揭示了引用计数机制在跨模块环境下的局限性,并提出了有效的解决方案。
3723

被折叠的 条评论
为什么被折叠?



