Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exporting and using static non-PODs sometimes causes an unavoidable problems #25

Open
KonstantinRitt opened this issue Dec 29, 2020 · 0 comments

Comments

@KonstantinRitt
Copy link
Contributor

KonstantinRitt commented Dec 29, 2020

According to 3.6.2

The storage for objects with static storage duration (basic.stc.static) shall be zero-initialized (dcl.init) before any other initialization takes place. Zero-initialization and initialization with a constant expression are collectively called static initialization; all other initialization is dynamic initialization. Objects of POD types (basic.types) with static storage duration initialized with constant expressions (expr.const) shall be initialized before any dynamic initialization takes place. Objects with static storage duration defined in namespace scope in the same translation unit and dynamically initialized shall be initialized in the order in which their definition appears in the translation unit.
..
It is implementation-defined whether or not the dynamic initialization (dcl.init, class.static, class.ctor, class.expl.init) of an object of namespace scope is done before the first statement of main. If the initialization is deferred to some point in time after the first statement of main, it shall occur before the first use of any function or object defined in the same translation unit as the object to be initialized.

The Android NDK's Clang/LLD sometimes produces an unloadable shared library and/or library that leads to crash when dlclose'd (depends on many things, including the target API version).
Their KnownIssues mentions similar issue with thread_local but I failed to find anything about exported namespaced static non-POD implementation guarantees/limitations, albeit there is a bunch of reports about crash during dlopen similar to what I sometimes see with my app built with NDK 21+/arm64 and running on Android O.

Look for example at:
// .h

QMDNSENGINE_EXPORT extern const QHostAddress MdnsIpv4Address;

// .cpp

const QHostAddress MdnsIpv4Address("224.0.0.251");

Depending on many things (including the linker, linkage type, whether QMdnsEngine::MdnsIpv4Address is referenced outside libqmdnsengine and so on), it is hard to guess when/where it's constructor shall be called.
Interestingly that decreasing the overall amount of static objects somehow solved this issue in my particular case.

A simple solution would be making MdnsIpv(4|6)Address a constexpr/inline function or making it a specialised enum + providing a respective overloads everywhere the object has been used before (i.e. Message::setAddress(SpecialAddress) => message.setAddress(QMdnsEngine::MdnsIpv4Address) ). Unfortunately, both will break source compatibility.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant