Troubleshooting
Problem
C++ exception handling does not behave as intended when mixing it with setjmp()/longjmp() functions.
Symptom
Programs that depend on C++ exceptions being automatically cleaned up may be affected by mixing setjmp()/longjmp() functions with C++ exceptions.
Consider the problematic test case below:
$cat test.cpp
#include <iostream>
#include <setjmp.h>
using namespace std;
main()
{
jmp_buf state;
int value = 0;
int count = 0;
value=setjmp(state);
printf ("val is %d\n",value);
++count;
try
{
if (count == 1)
throw 1;
}
catch (...)
{
printf ("In catch before longjmp\n");
longjmp(state, 1);
printf ("In catch after longjmp\n");
}
printf ("After try catch\n");
return 0;
}
$
Cause
The C++ standard mentions that the interaction between setjmp()/longjmp() with C++ exceptions (and normal end of scope clean up) is undefined.
On AIX, calling longjmp() from inside the catch block will bypass all destructor calls at the end of a scope and the clean up of the C++ exception.
Environment
AIX
Diagnosing The Problem
The problem can be diagnosed by using the profiled C++ Runtime where you can analyze the ehlogs and see the missing destructors calls and C++ exception clean up functions.
Example of missing cleaup functions for test.cpp from above:
$ cat ehlog43188270-f066cbd4-1.log
0:74187005:v6:
1:74187005:v6:DOTHROW: ----------------------------starting exception processing-----------------------------
2:74187005:v6:Throwing exception, name:(i:0), sp(0x2ff229e0)
3:74187005:v6:pc(0x1000072c), nested(no),
.
.
.28:74187005:v6:..leaving DoThrow for a catch block
29:74187005:v6:DOTHROW: ----------------------------ending exception processing-----------------------------
.
.
//Normally, there would be a CLEANUP section here
$
Resolving The Problem
The problem can be resolved by avoiding setjmp()/longjmp() functions within the 'try-catch' blocks.
One solution would be to detect, via a 'flag' variable, that an exception was caught; and then using the longjmp() function call outside of the try-catch block depending on the value of the 'flag' variable.
Example:
$
.
catch
{
flag = 1;
}
if (flag == 1) longjmp(state, 1);
.
$
By bringing out the longjmp() from the try-cath block, you will notice that the ehlogs will now contain the CLEANUP sections:
$cat ehlog43188270-f066cbd4-1.log
.
.
32:69009571:v6:CLEANUP: ----------------------------starting exception cleaning-----------------------------
33:69009571:v6:Cleaning up Exception, catch_state(1), cleanup ctr(1)
34:69009571:v6:---- Exception Chain Empty ----
.
.
$
Was this topic helpful?
Document Information
Modified date:
06 December 2018
UID
swg21590839