SEH Termination Blocks (C++)

From RAD Studio
Jump to: navigation, search

Go Up to Structured Exceptions Under Win32 (C++)

The structured exception handling model supports a "termination block" which is executed whether a guarded block is exited normally or via an exception. The C++Builder compiler supports this in C with the following syntax:

__try {
    func();
}
__finally {
    // this happens whether func() raises an exception or not
}

Termination blocks are supported by a C++ extension where you can handle cleanup in the __finally block:

try {
    func();
}
__finally {
    // this happens whether func() raises an exception or not
}

The following example illustrates termination blocks:

/* Program results:
 An exception:
 Caught an exception.
 The __finally is executed too!
 No exception:
 No exception happened, but __finally still executes!
 */
#include <stdio.h>
#include <windows.h>

int main() {
	float e, f, g;
	try {
		f = 1.0;
		g = 0.0;
		try {
			puts("An exception:");
			e = f / g;
		}
		__except (EXCEPTION_EXECUTE_HANDLER) {
			puts("Caught an exception.");
		}
	}
	__finally {
		puts("The __finally is executed too!");
	}
	try {
		f = 1.0;
		g = 2.0;
		try {
			puts("No exception:");
			e = f / g;
		}
		__except (EXCEPTION_EXECUTE_HANDLER) {
			puts("Caught an exception.");
		}
	}
	__finally {
		puts("No exception happened, but __finally still executes!");
	}
	return e;
}

C++ code can also handle a "termination block" by creating local objects with destructors that are called when the scope is exited. Since C++Builder structured exceptions support destructor cleanup, this will work regardless of the type of exception raised.

Note: One special case concerns what happens when an exception is raised and never handled by the program. For a C++ exception, the C++Builder compiler calls destructors for local objects (not required by the language definition), whereas with an unhandled Win32 exception, destructor cleanup does not happen.

Note: Standard C++ does not support finally blocks. Instead, it tends to use destructors to handle the freeing of resources. However, when working with VCL, which is written in Delphi, finally blocks are an important tool because of the way VCL objects must be allocated on the heap.

See Also