.\" -*-nroff-*- .TH control 3 "28 April 2023" "Straylight/Edgeware" "FINALLY macro package" .SH NAME FINALLY \- defer execution until scope exit .SH SYNOPSIS .nf .B "#include " .BI FINALLY( stmt ); .BI FINALLY_TAGGED( tag ", " stmt ); .fi . .SH DESCRIPTION . .SS "General usage of FINALLY" The .B FINALLY macro arranges that the statement .I stmt should be executed when control leaves the immediately enclosing scope, whether this is by just running off the end, or by explicit control flow, e.g., .BR return , .BR goto , .BR break, or .BR continue . If a scope contains multiple .B FINALLY calls, then the statements are executed in reverse order. .PP In particular, if the macro call is placed at top-level within a function body, then .I stmt is executed when the function returns, either as a result of a .B return statement, or by running off the end of the function body. .PP With GNU-like compilers, you can arrange for the statement to be executed when control escapes the scope as the result of a C++ exception by setting the .B \-fexceptions compiler flag. .PP The statement will .I not be executed if control leaves the scope as a result of .BR longjmp (3) or similar. It also won't be executed if control `leaves' as a result of a call to .BR exit (3) or similar; but that's almost certainly what you want. .PP The .B FINALLY macro's expansion is syntactically one or more declarations. In C89 code, therefore, it must appear at the head of a block, before any statements. In C99 or later, it may appear anywhere in a block. However, because it may expand to more than one declaration, it is not suitable for use in a .B for statement. . .SS "Macros and FINALLY_TAGGED" At most one use of .B FINALLY can occur on any given line of source code. In particular, this rule forbids macros which expand into more than one use of .BR FINALLY , since the macro expansions will cause them all to be credited to the line holding the original expansion site. To avoid trouble, macro authors should use .B FINALLY_TAGGED instead. Each use of .B FINALLY_TAGGED on the same source line must have a distinct .I tag argument, which may be any identifier. . .SS "Nonlocal transfers, and thread and process exits" The statement will .I not be executed if control leaves the scope as a result of .BR longjmp (3) or similar. It also won't be executed if control `leaves' as a result of a call to .BR exit (3), .BR pthread_exit (3), .BR thrd_exit (3), or similar. .PP You didn't want .B FINALLY blocks to run at .BR exit (3) time. Almost all uses of .B FINALLY are to release process-local resources such as memory, file descriptors or locks, or something else similar. The kernel will release these by itself when the process exits, because leaking resources when processes crash would just be too awful to consider. All you'd achieve by carefully freeing memory prior to .BR exit (3) would be to waste time. . .SS "Setup and configuration" The .B FINALLY macro uses compiler-specific techniques. Not only does it need different implementations on different compilers, but it may require unusual compiler options and runtime support libraries to work. .PP Firstly, the .B header can work portably under C++11 or later, using RAII and lambdas: idiomatic C++ doesn't benefit much from this, but the facility is there anyway. If the header detects that such a compiler is in use (the macro .B __cplusplus is defined to a value greater than or equal to 201103), then it will use the C++-specific implementation. .PP Otherwise, the header checks the value of .BR FINALLY_CONFIG_FLAVOUR : it should be one of the following options. .TP .B NIL No support. An error is reported (using .BR #error ). .TP .B GCC_NESTED_FUNCTIONS Use the GNU C Compiler's support for nested functions and the .B cleanup function attribute. Note that this use of nested functions does not involve the use of trampolines, and does not require an executable stack. (This is verified as part of the package tests.) .TP .B CLANG_BLOCKS Use the LLVM Clang compiler's support for `blocks' and the .B cleanup function attribute. Depending on the environment, this may require the .B \-fblocks compiler option, and linking against the .B \-lBlocksRuntime library. .IP Support is only partial. When the statement is executed on exit from its scope, it sees the variable values that were current when the .B FINALLY declaration was processed, and not any changes since. As a result of this bug, the .B header will fail unless the macro .B FINALLY_TOLERATE_BUG_CAPTURE_COPIES is defined to a nonzero value, and will set .B FINALLY_BUG_CAPTURE_COPIES for your program to act on. .PP If .B FINALLY_CONFIG_FLAVOUR is not set, then .B guesses one of these flavours based on the compiler version and other predefined macros. This guess may be wrong, and things may not work anyway because necessary compiler options or libraries aren't available. .PP The best way to set everything up correctly is to use the provided .B FINALLY_CHECK Autoconf macro. It will define .B FINALLY_CONFIG_FLAVOUR to a suitable value, and also report necessary compiler flags and libraries in the .B FINALLY_CFLAGS and .B FINALLY_LIBS makefile variables. See the .B finally.m4 file's internal documentation for the details. . .SH BUGS The selection of supported compilers is extremely limited. .PP Clang doesn't work properly because its `blocks' capture a copy of the outer scope's variables, rather than closing over them properly. . .SH AUTHOR Mark Wooding,