天极Yesky
  • 笔记本电脑
    笔记本
  • 台式电脑
    台式机
  • 手机
    手机
  • 电脑硬件DIY
    DIY硬件
  • CPU
    主板
    音箱
  • 硬盘
    显卡
    键鼠
  • 内存光驱
    显示器
    机箱电源

  • 数码相机DC
    数码相机
  • MP3播放器
    MP3/MP4
  • 数码摄像机DV
    摄像机
  • 电脑外设
    外设
  • 网络
    网络
  • 服务器
    服务器
  • 数字家庭
    数字家庭
  • 群乐
    群乐
  • 产品报价 行情 经销商 渠道 评测 | 软件 设计 网页 开发 安全 论坛 E时代 游戏 图片 壁纸 下载 网摘 博客 索尼专区 Vista 科技奥运
    天极网
    Resources and resource leaks
    作者: InformIT
    出处:
    责任编辑:
    [ 2004-06-17 19:28 ]


    Resources and resource leaks
    Bjarne Stroustrup

    We have all been plagued by memory leaks, but it's even more galling than normal when the memory leak comes in a program that we are writing. This tip, a portion of an article on InformIT, titled Programming with Exceptions, discusses one method of eliminating resource leaks.

    Bjarne Stroustrup is the author of C++ Programming Language, the Special Edition.


    Consider a traditional piece of code:

     
    void use_file(const char* fn) 
    { 
            FILE* f = fopen(fn,"r"); 
            // use f 
            fclose(f); 
    } 
    

    This code looks plausible. However, if something goes wrong after the call of fopen() and before the call of fclose(), it's possible to exit use_file() without calling fclose(). In particular, an exception might be thrown in the use f code, or in a function called from there. Even an ordinary return could bypass fclose(f), but that's more likely to be noticed by a programmer or by testing.

    A typical first attempt to make use_file() fault-tolerant looks like this:

     
    void use_file(const char* fn) 
    { 
            FILE* f = fopen(fn,"r"); 
            try { 
                    // use f 
            } 
            catch (...) { 
                    fclose(f); 
                    throw; 
            } 
            fclose(f); 
    } 
    

    The code using the file is enclosed in a try block that catches every exception, closes the file, and re-throws the exception.

    The problem with this solution is that it's ad hoc, verbose, tedious, and potentially expensive. Another problem is that the programmer has to remember to apply this solution everywhere a file is opened, and must get it right every time. Such ad hoc solutions are inherently error-prone. Fortunately, there is a more elegant solution.

    It's a fundamental rule that when a variable goes out of scope its destructor is called. This is true even if the scope is exited by an exception. Therefore, if we can get a destructor for a local variable to close the file, we have a solution. For example, we can define a class File_ptr that acts like a FILE*:

     
    class File_ptr { 
            FILE* p; 
    public: 
            File_ptr(const char* n, const char* a) { p = fopen(n,a); } 
            // suitable copy operations 
            ~File_ptr() { if (p) fclose(p); } 
     
            operator FILE*() { return p; }   // extract pointer for use 
    }; 
    

    Given that, our function shrinks to this minimum:

     
    void use_file(const char* fn) 
    { 
            File_ptr f(fn,"r"); 
            // use f 
    } 
    

    The destructor will be called independently of whether the function is exited normally or exited because an exception is thrown. That is, the exception-handling mechanism enables us to remove the error-handling code from the main algorithm. The resulting code is simpler and less error-prone than its traditional counterpart.

    The file example is a fairly ordinary resource leak problem. A resource is anything that our code acquires from somewhere and needs to give back. A resource that is not properly "given back" (released) is said to be leaked. Other examples of common resources are memory, sockets, and thread handles. Resource management is the heart of many programs. Typically, we want to make sure than every resource is properly released, whether we use exceptions or not.

    You could say that I have merely shifted the complexity away from the use_file() function into the File_ptr class. That's true, but I need only write the File_ptr once for a program, and I often open files more frequently than that. In general, to use this technique we need one small "resource handle class'' for each kind of resource in a system. Some libraries provide such classes for the resources they offer, so the application programmer is saved that task.

    The C++ standard library provides auto_ptr for holding individual objects. It also provides containers, notably vector and string, for managing sequences of objects.

    The technique of having a constructor acquire a resource and a destructor release it is usually called resource acquisition is initialization.


    You can read this entire article at InformIT. You have to register there to see the article, but registration is free.

    笔名:
    请您注意:

     遵守国家有关法律、法规,尊重网上道德,承担一切因您的行为而直接或间接引起的法律责任。

     天极网拥有管理笔名和留言的一切权利。
    相关内容