Actually it was so obvious - I just haven't read the C++ standard and was writing throw()
specification thinking it would allow all exceptions - instead it turned out it was the exact opposite.
And yes this throw
function specification is what is causing those zero TryBlockMap with more than one Unwind entries. Here is a VC++ 6.0 (and later) compilable example (view dissasembly of f
):
#include <stdio.h>
struct B {
int a, b;
};
struct B1 {
B1() {};
B1(const B1& tmp) {
a1 = tmp.a1;
printf("B1::B1 copy constr\n");
}
~B1() {
printf("~B1()\n");
}
int a1, b1;
};
struct A : B, B1 {
int b, c;
};
struct A f() throw(int) {
struct A tmp;
return tmp;
}
int main() {
f();
}
With two unwind entries. The tricky part in that scenario is that throw
specification is not added to the type of the function so even if you have debug symbols (PDB) - you still will have your head banging against the wall.
EDIT: Actually the above example won't work for newer versions of MSVC - if you want to do it there you would need to add a try
- catch
block encapsulating the f()
call.
Also the class A
and all of it's parents were a test case for another question related to the topic of C++ exception if you want to learn more but otherwise I don't think this exact structure is necessary to trigger the generation of FunctionInfo with zero TryBlocks. There just need to be something going on in f
I think.