← 返回首页
Resource not released in destructor — CodeQL query help documentation CodeQL docs
CodeQL documentation
CodeQL resources

Resource not released in destructor

ID: cpp/resource-not-released-in-destructor Kind: problem Security severity: Severity: warning Precision: high Tags: - efficiency - readability - external/cwe/cwe-404 - external/jsf Query suites: - cpp-security-and-quality.qls

Click to see the query in the CodeQL repository

This rule finds resources that are allocated by a class, but not released in the destructor of that class. Allocating a resource includes:

Recommendation

If the resource is not being released at all, ensure that the class does release the resource, normally by adding the release to the destructor of the class. This change needs to be carefully validated: client code may be relying on the resource outliving the class that allocated it, and must be reviewed and updated if necessary.

In the other case, for instance a class that has an explicit close function, the aim is to migrate the class to a straightforward RAII pattern. This can be achieved in several steps:

  1. First, ensure that the close function (or its equivalent) is safe to call twice, by releasing resources only if they have not been released before.

  2. Next, call the close function from the destructor. This does not require changing the client code, since it is safe to call it twice.

  3. Migrate client code to remove direct uses of the close function, taking the opportunity to check that the object itself is being deleted appropriately.

  4. Finally, when possible also migrate initialization code to the constructor of the class to make it follow the RAII pattern precisely.

Example

// This class opens a file but never closes it. Even its clients // cannot close the file class ResourceLeak { private: int sockfd; FILE* file; public: C() { sockfd = socket(AF_INET, SOCK_STREAM, 0); } void f() { file = fopen("foo.txt", "r"); ... } }; // This class relies on its client to release any stream it // allocates. Note that this means the client must have // intimate knowledge of the implementation of the class to // decide whether it is safe to release the stream. class StreamPool { private: Stream *instance; public: Stream *createStream(char *name) { if (!instance) instance = new Stream(name); return instance; } } // This class handles its resources, but does not do that in // the constructor/destructor. It can be rewritten easily to // be safer to use. class StreamHandler { private: char *_name; Stream *stream; public: C(char *name) { _name = strdup(name): } void open() { stream = new Stream(); } void close() { delete stream; } ~StreamHandler() { free(_name); // stream should be deleted here, not in close() } }

References