fopen 资源泄露问题的解决方案

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.

In the project security scan , the result told me that the function fopen maybe cause the resource leak. i find the good article topic for this issue.  as below:

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 classFile_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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值