Resource Leaks and Strong Resource Safety
A resource handle is an object that manages a resource, and it can be used as an alternative to pointers in many cases.
Where Does the Release Happen?
Many programs acquire something they must later give back. The three examples the source names are memory, a thread of execution, and a file. When that work is done by hand with raw pointers, every acquisition needs a matching release, and the programmer must remember to write that release at every place the code could leave. Forgetting one of those releases is how a resource leak happens: a resource is acquired and never given back.
Keep one question in mind as you read this article: when the code is finished with a resource, which piece of code is responsible for releasing it? The answer changes depending on whether you use a raw pointer or a resource handle, and that difference is the central idea here.
What do you think happens?
What do you think releases the resource when the function is finished with it?
Reveal answer
The handle releases the resource as its own lifetime ends
The source explains that with a handle, the responsibility for releasing a resource is carried by the handle rather than written by hand at every point where the code could leave. The handle is an ordinary object with a lifetime, and when that lifetime ends, the handle releases the resource it manages.
Tracing a Raw Pointer Through a Function
Consider a simple scenario. A function obtains a resource, uses it for some work, and then finishes. With a raw pointer, the function holds a plain address. Nothing about that address says whether the resource still needs to be released, or who should do it. The release is a separate action that the programmer must place correctly, and it must happen on every path out of the function.
Following a raw pointer through a function that can exit early
A function acquires a resource, stores its address in a raw pointer, and then performs work. Partway through, an error check decides the function should stop early. Trace who is responsible for the release.
- 1Step 1: Acquire
The function obtains the resource and holds only a plain address to it. The pointer itself does not record that a release is owed.
- 2Step 2: Use
The function works with the resource through the pointer. Nothing in the pointer changes to show the resource is still held.
- 3Step 3: Early exit
The error check causes the function to leave before reaching its normal end. If the programmer did not place a release on this path, the resource is never given back.
- 4Step 4: Normal exit
On the normal path, the programmer must separately place a release. The function now needs a release on both paths, and the programmer has to remember both.
The programmer is responsible for the release, and that responsibility must be written correctly on every exit path. A missed path is a leak.
This scenario is not a claim that raw pointers are useless. The problem is that a bare pointer does not tell the program who owns the resource or when it should be released, so that responsibility has to be spelled out everywhere the function can end.
What a Resource Handle Is
A resource handle is an object that manages a resource, and it can be used as an alternative to pointers in many cases.
With a resource handle, the same scenario is organized differently. The handle is the object that holds the resource, and its job includes releasing it. The function works with the handle rather than with the bare pointer. Responsibility for the release is attached to the handle, not spread across the lines of code that happen to use the resource.
The phrase alternative to pointers is important. A handle does not usually replace the idea of a resource. It replaces the way the program would otherwise hold a resource and track it. The resource still exists, and something still has to manage it. A handle takes over that management role so that the rest of the code does not have to.
| Aspect | Raw pointer | Resource handle |
|---|---|---|
| What it stores | A plain address with no statement about ownership | An object that holds and manages the resource |
| Who is responsible for release | The programmer, by writing a release action in the right places | The handle, as a consequence of its role as the resource manager |
| What the caller must remember | To release the resource on every path out of the function | To work with the handle; its lifetime carries the release |
| Where the release lives | Spread across the code that uses the resource | Attached to the handle object |
How a raw pointer and a resource handle differ in what they store, who releases the resource, and what the caller must remember.
Who Holds the Resource and Who Releases It
When a handle wraps a resource, three things are involved: the application code, the handle, and the resource itself. Read the diagram from top to bottom. Application code works with the handle. The handle is the object that stands in front of the resource and manages it. The resource is the thing being held, such as memory, a system thread, or a file handle.
The answer to the central question is now clear. The resource is held by the handle, and the handle is the object responsible for giving it back. The application code uses the resource through the handle, but it does not need to be the piece of code that performs the release. The source describes the handle as the object whose job includes releasing the resource it manages.
Tracing a Handle's Lifetime
A handle is a normal object with a lifetime. The timeline below follows one handle-managed resource from acquisition through release. The important point is the step near the end: the release is tied to the handle's lifetime ending, not to a separate line the programmer must write at each exit.
Because the release is tied to the handle's lifetime, the programmer does not need a separate release step at each place where the function can end. Whether the function finishes normally or leaves early, the handle's lifetime comes to an end and the resource it manages is released. The source does not walk through every control-flow case, but this is the mechanism that lets handles eliminate leaks.
Standard Library Handles
The source names several familiar standard-library types that are resource handles. Each one holds a different kind of resource, which shows how broad the idea is. The list below is the set the source gives, with the resource each one holds.
- vector manages memory on the program's behalf
- thread manages a system thread
- fstream manages a file handle
unique_ptris a standard smart pointer and is also a handle
Notice that vector appears even though many people think of it as a container. The source classifies it as a handle because it holds memory on the program's behalf. The same classification applies to thread and fstream. Unique_ptr matters for a related reason: the source notes that the standard-library smart pointers are themselves resource handles, so a unique_ptr is an example of the same pattern discussed here, not a separate topic.
Strong Resource Safety and Leaks
Strong resource safety means eliminating resource leaks for a general notion of a resource. Resource handles are the mechanism the source highlights for achieving it without added overhead.
The phrase general notion of a resource matters. The source does not limit the idea to memory. It names memory, system threads, and file handles as examples of resources. Strong resource safety aims at all of these, so a leak in a thread or a file is as much the target as a leak of memory.
Read the two columns side by side. In the raw pointer column, the release is a step the programmer must remember to perform, and if it is skipped on some path, the resource leaks. In the handle column, the release is a consequence of the handle's role as the resource's manager. The source describes this as making pointers disappear into resource handles, so that the code using the resource no longer has to carry the bookkeeping itself.
Mistakes About Handles and Leaks
Common mistake Believing a handle removes the need for a resource
Why it failsThe source says the resource still exists and something still has to manage it. A handle takes over the management role, it does not make the resource unnecessary.
Do this insteadThink of the handle as the manager of the resource. The resource is still acquired and used; the handle is responsible for giving it back.
Common mistake Treating vector only as a container and not as a resource handle
Why it failsThe source classifies vector as a handle because it holds memory on the program's behalf.
Do this insteadRecognize vector as the same pattern as thread and fstream: an object that holds a resource and manages it.
Common mistake Assuming leaks only concern memory
Why it failsThe source uses a general notion of a resource that includes system threads and file handles, so a leak in either is part of the target of strong resource safety.
Do this insteadWhen checking for leaks, ask about every kind of resource the code acquires, not only memory.
Common mistake Reading the release as a line you must still write at every exit point
Why it failsWith a handle, the release is tied to the handle's lifetime. The source describes it as a consequence of the handle's role, not a separate step at each place the code can leave.
Do this insteadIdentify which object's lifetime governs the release, and check that the resource is owned by that object.
Trace a Handle-Managed Function
A function acquires a file through a handle, reads from it, and then returns early because of a condition in the middle of its work. Trace the lifetime of the handle and the file. Which object is responsible for releasing the file, and on which exit paths must the programmer write a release action?
Hints
- Ask which object holds the file and which object's lifetime governs the release.
- Compare the early return path with the normal path. Does the handle's lifetime end on both?
- The source says that with a handle, the release is carried by the handle rather than written at every exit point.
Key Takeaways
- A resource handle is an object that manages a resource, and it can be used as an alternative to pointers in many cases.
- With a raw pointer, the programmer must place a release on every path out of the code; with a handle, the release is carried by the handle, tied to its lifetime.
- The handle holds the resource and is responsible for releasing it, while application code works with the handle rather than with the bare resource.
- Strong resource safety means eliminating resource leaks for a general notion of a resource, including memory, system threads, and file handles, and resource handles are the mechanism the source highlights for achieving it without added overhead.