`
febird
  • 浏览: 254258 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

千万注意,不要 hack std::string

    博客分类:
  • C++
阅读更多

前段时间被一个bug折磨了两个星期,最后发现竟然是如此一个陷阱——我为了减少内存用量并且减少一次内存拷贝,直接通过string.data()修改了string的内部表示。这与其说是一个陷阱,不如说是我自己给自己造了一个陷阱然后把自己给掉进去了。发病机制可以用如下代码简单的勾画出来:

using namespace std;

 

int main(int argc, char* argv[])

{

    string str1 = "abcde";

    string str2 = str1;

 

    strcpy(const_cast<char*>(str2.data()), "1234");

 

    cout << "str1=" << str1 << endl

         << "str2=" << str2 << endl;

 

    return 0;

}

 

在windows+msvc 中的输出是:

str1=abcde
str2=1234


在linux+gcc中的输出是:

str1=1234
str2=1234

在boost::serialization中,对string的load也是采用这样的hack方式,目的也是为了减少内存用量并且减少一次内存拷贝。使用boost::serialization的同志们需要注意,不要掉进这个陷阱!

我们可以看出,在msvc中,string拷贝时是真拷贝,而在gcc中,必定是用了引用计数+copy on write。str1和str2内部引用的是同一块内存。因为string.data()和string.c_str()都是const成员,所以不会有copy,只会增加引用计数。所以导致修改str2实际上也修改了str1。

c++标准甚至允许把const string的成员放入带写保护的内存区域中,或者把string的成员实际上存储在不相邻的内存块中,而仅在调用 string.data() 或 string.c_str() 时将数据拷贝到一块临时内存中然后返回,这块临时内存将在下一次调用string的一个非const成员函数时释放,如果目标平台真这样实现,往 string.data()中写数据就会导致更加微妙的错误。

 

分享到:
评论

相关推荐

    effective的学习心得,希望可以帮助大家

    - 指针对象类通常使用引用计数来管理资源,如std::shared_ptr和std::unique_ptr。 13. **资源访问**: - 提供`get()`函数提供对原始资源的安全访问,但不直接暴露资源所有权。 - 可以通过重载`-&gt;`或`.`运算符...

    tricks-and-hacks:C ++中的漂亮程序

    熟练使用STL能极大提升代码的简洁性和效率,例如,使用`std::sort`快速对数组或容器进行排序。 3. **RAII(Resource Acquisition Is Initialization)**: C++鼓励使用资源管理类,如智能指针(shared_ptr、unique_...

    Qemu-1.0.1 for windows

    -win2k-hack use it when installing Windows 2000 to avoid a disk full bug -no-fd-bootchk disable boot signature checking for floppy disks -no-acpi disable ACPI -no-hpet disable HPET -balloon none ...

    qemu-0.13.0(编译过全处理器支持)

    -win2k-hack use it when installing Windows 2000 to avoid a disk full bug -no-fd-bootchk disable boot signature checking for floppy disks -no-acpi disable ACPI -no-hpet disable HPET -balloon none ...

Global site tag (gtag.js) - Google Analytics