On Tue, 17 Nov 2020 at 18:58, David Hagood via Gcc-help <gcc-help@xxxxxxxxxxx> wrote: > > You are squarely into "undefined behavior" territory here: > > > > static int throw314() > > { > > std::cout << "throw314() called\n" << std::flush; > > throw 3.14f; > > } > > > > static int throwDuringInitialization = throw314(); > > You are throwing from a constructor. That's STRONGLY discouraged - it No it isn't. > leads to undefined behavior, No it doesn't. > as you cannot tell how much of an object > has been constructed, and thus how much can be safely torn down. It's The C++ language is quite clear. The base class and member subobjects that have already been constructed will get destroyed in reverse order of construction. > far better to have a function to be called after the constructor has > completed, and let that function throw if needed, so that you can be > sure all objects are fully constructed (and thus can be destructed) > before the exception can cause problems. Two-stage initialization is strongly discouraged. They create partially-formed objects that can't be used. Far better to use exceptions in a constructor to report failure. That's one of the main reasons exceptions were added to C++ in the first place. But that's irrelevant here, since the object being constructed is an int. > > > > int main() { > > > > try { > > void* handle = dlopen("throw_in_static_init.so", RTLD_LAZY); > > std::cout << "Lib loading: " << (handle ? "successfull" : "failed") << "\n"; > > } catch (float f) { > > std::cout << "Exception caught in main function: " << f << std::endl; > > } > > It's also a really bad idea to throw an exception from within a C > function (dlopen). Ideally, any function with extern "C" linkage should > avoid any C++ specific concepts, like exceptions. The compiler won't > have done all the homework in dlopen for things like unwinding the stack > in an exception, since exceptions don't exist in C. Nothing on the stack of dlopen has a destructor, so unwinding is a no-op. GCC tries to ensure it works in general. > If you need your shared library to do some initialization that > potentially could fail, you should probably define a C++ function within > the shared library that does the exception, and will be called after the > dlopen completes successfully. > > > I suggest you get the Scott Meyer books "Effective C++" and “More > Effective C++” and read them thoroughly. I don't think either of them covers dlopen, does it? Item 10 in More Effective C++ specifically deals with what happens when constructors throw, and doesn't say to avoid it.