I actually have both a hard time imagining a better language (not saying it's impossible, just that it's not trivial for me to see) and also how ownership would resolve this issue. Could you elaborate?
libvirt has long been linked with -Wl,-z -Wl,nodelete to avoid this:
https://gitlab.com/libvirt/libvirt/-/commit/8e44e5593eb9b89f...
Another case in libnbd which really demonstrates how hard this is:
https://gitlab.com/nbdkit/libnbd/-/commit/368e3d0d5a8871aad5...
How is this different from holding a pointer to an object being deleted?
I came to accept that in languages like C and C++, the best path for dynamic loading code is really via OS IPC and external processes, the decrease in hardware resources and simpler programming model of using shared libraries as plugins, isn't worth the endless amount of debugging hours regarding program crashes.