• 【转】string的内存共享和CopyOnWrite技术


    转自:http://hi.baidu.com/zoupng/blog/item/becaa4f42e1d396bdcc474fb.html

    2.4、         臭虫Bug

    是谁说的“有太阳的地方就会有黑暗”?或许我们中的许多人都很迷信标准的东西,认为其是久经考验,不可能出错的。呵呵,千万不要有这种迷信,因为任何设计再好,编码再好的代码在某一特定的情况下都会有Bug,STL同样如此,string类的这个共享内存/写时才拷贝技术也不例外,而且这个Bug或许还会让你的整个程序crash掉!

    不信?!那么让我们来看一个测试案例:

    假设有一个动态链接库(叫myNet.dll或myNet.so)中有这样一个函数返回的是string类:

    string GetIPAddress(string hostname)

    {

        static string ip;

        ……

        ……

        return ip;

    }

    而你的主程序中动态地载入这个动态链接库,并调用其中的这个函数:

    main()

    {

    //载入动态链接库中的函数

    hDll = LoadLibraray(…..);

    pFun = GetModule(hDll, “GetIPAddress”);

    //调用动态链接库中的函数

    string ip = (*pFun)(“host1”);

    ……

    ……

    //释放动态链接库

    FreeLibrary(hDll);

    ……

    cout << ip << endl;

    }

    让我们来看看这段代码,程序以动态方式载入动态链接库中的函数,然后以函数指针的方式调用动态链接库中的函数,并把返回值放在一个string类中,然后释放了这个动态链接库。释放后,输入ip的内容。

    根据函数的定义,我们知道函数是“值返回”的,所以,函数返回时,一定会调用拷贝构造函数,又根据string类的内存共享机制,在主程序中变量ip是和函数内部的那个静态string变量共享内存(这块内存区是在动态链接库的地址空间的)。而我们假设在整个主程序中都没有对ip的值进行修改过。那么在当主程序释放了动态链接库后,那个共享的内存区也随之释放。所以,以后对ip的访问,必然做造成内存地址访问非法,造成程序crash。即使你在以后没有使用到ip这个变量,那么在主程序退出时也会发生内存访问异常,因为程序退出时,ip会析构,在析构时就会发生内存访问异常。

    内存访问异常,意味着两件事:1)无论你的程序再漂亮,都会因为这个错误变得暗淡无光,你的声誉也会因为这个错误受到损失。2)未来的一段时间,你会被这个系统级错误所煎熬(在C++世界中,找到并排除这种内存错误并不是一件容易的事情)。这是C/C++程序员永远的心头之痛,千里之堤,溃于蚁穴。而如果你不清楚string类的这种特征,在成千上万行代码中找这样一个内存异常,简直就是一场噩梦。

    备注:要改正上述的Bug,有很多种方法,这里提供一种仅供参考:

    string ip = (*pFun)(“host1”).cstr();

    3、             后记

    文章到这里也应该结束了,这篇文章的主要有以下几个目的:

    1)    向大家介绍一下写时才拷贝/内存共享这种技术。

    2)    以STL中的string类为例,向大家介绍了一种设计模式。

    3)    在C++世界中,无论你的设计怎么精巧,代码怎么稳固,都难以照顾到所有的情况。智能指针更是一个典型的例子,无论你怎么设计,都会有非常严重的BUG。

    4)    C++是一把双刃剑,只有了解了原理,你才能更好的使用C++。否则,必将引火烧身。如果你在设计和使用类库时有一种“玩C++就像玩火,必须千万小心”的感觉,那么你就入门了,等你能把这股“火”控制的得心应手时,那才是学成了。

    最后,还是利用这个后序,介绍一下自己。我目前从事于所有Unix平台下的软件研发,主要是做系统级的产品软件研发,对于下一代的计算机革命——网格计算非常地感兴趣,同于对于分布式计算、P2P、Web Service、J2EE技术方向也很感兴趣,另外,对于项目实施、团队管理、项目管理也小有心得,希望同样和我战斗在“技术和管理并重”的阵线上的年轻一代,能够和我多多地交流。我的MSN和邮件是:haoel@hotmail.com

    我的专栏是:

    http://blog.csdn.net/haoel/

  • 相关阅读:
    Python 元类
    Rsync 基础配置
    linux shell find
    找最大的目录
    云主机的上下行带宽
    关于c3p0 ResourcePoolException: Attempted to use a closed or broken resource pool
    recover_file
    MegaCli 监控raid状态
    influxdb
    在Ubuntu 16.04如何安装Java使用apt-get的
  • 原文地址:https://www.cnblogs.com/xuyuan77/p/1272577.html
Copyright © 2020-2023  润新知