Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Consider using
gsl::finally
if final action is intended (gsl.util)
C++ Core Guidelines: GSL.util: Utilities
The Guidelines Support Library provides a convenient utility to implement the final action concept. Since the C++ language doesn't support try-finally constructs, it became common to implement custom cleanup types that would invoke arbitrary actions on destruction. The gsl::finally
utility is implemented in this way and provides a more uniform way to perform final actions across a code base.
There are also cases where final actions are performed in an old-fashioned C-style way by using goto
statements (which is discouraged by C26438 NO_GOTO). It's hard to detect the exact intention in code that heavily uses goto
, but some heuristics can help to find better candidates for cleanup.
Remarks
- This rule is lightweight and uses label names to guess about opportunities to use final action objects.
- Label names that can raise a warning contain words like "end", "final", "clean", and so on.
- Warnings appear at the
goto
statements. You may see verbose output on some occasions, but the output may help in prioritizing code, depending on its complexity. - This rule always goes in pair with C26438 NO_GOTO. Depending on the priorities, one of these rules can be disabled.
Code analysis name: USE_GSL_FINALLY
Example
Cleanup with multiple goto statements:
void poll(connection_info info) { connection c = {}; if (!c.open(info)) return; while (c.wait()) { connection::header h{}; connection::signature s{}; if (!c.read_header(h)) goto end; // C26448 and C26438 if (!c.read_signature(s)) goto end; // C26448 and C26438 // ... } end: c.close(); }
Cleanup with multiple goto statements replaced by gsl::finally
:
void poll(connection_info info) { connection c = {}; if (!c.open(info)) return; auto end = gsl::finally([&c] { c.close(); }); while (c.wait()) { connection::header h{}; connection::signature s{}; if (!c.read_header(h)) return; if (!c.read_signature(s)) return; // ... } }