Re: Strange exception handling behaviour with dlopen()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.




[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux