An exchange session opens a socket, registers with a sequencer and takes a shared memory lock. The current code releases all three at the end of the function and again in three catch blocks. Say what goes wrong, describe the RAII structure that fixes it, and state the one rule the destructors must obey.

An exchange session opens a socket, registers with a sequencer and takes a shared memory lock. The current code releases all three at the end of the function and again in three catch blocks. Say what goes wrong, describe the RAII structure that fixes it, and state the one rule the destructors must obey.

Approach: Ask which exits from the function the explicit cleanup fails to cover, then think about what the language guarantees to run on every exit path including a thrown exception.

Explicit cleanup misses any early return added later and any exception thrown part way through acquisition, and it releases in the wrong order after a partial failure; give each resource its own RAII guard type that acquires in its constructor and releases in its destructor, declare them as locals in acquisition order, and let destructor order run them in reverse automatically, with the one rule that a destructor must never throw. Each guard owns exactly one resource, so a failure half way through unwinds only what was actually acquired, which is the resource ownership property the catch blocks were trying to reproduce by hand. Reverse order matters because the sequencer registration depends on the socket still being open. A destructor that throws during stack unwinding calls terminate, so the release path logs and swallows its own errors, and anything that can genuinely fail gets an explicit close the caller may call and check first. Make each guard non-copyable and movable so ownership is unambiguous.

Follow-up: How would you express the same guarantee for a resource whose release can block for 200 milliseconds?

Key concepts: raii, destructor order, stack unwinding, resource ownership.