C++ Logo

std-proposals

Advanced search

Re: Make side effects in static initialization more consistent

From: Marcin Jaczewski <marcinjaczewski86_at_[hidden]>
Date: Mon, 21 Dec 2020 13:12:08 +0100
Isn't this break of As-If rule? Linker can remove variables only if
you cannot detect that.
If constructor/initialization did some not trivial thing then you can
clearly see the difference if it was run or not.
Variable itself could disappear but side effects should stay.

It is possible that there is some clause in the standard that allows
this but if we fix it we should alter it not adding new things.

pon., 21 gru 2020 o 12:06 kh via Std-Proposals
<std-proposals_at_[hidden]> napisaƂ(a):
>
> Initialization of variables might carry side effects. The behavior for
> these effects is usually well-defined. One exception is the
> initialization of global variables with static storage duration.
>
> The main problem is that the linker could remove unused variables. The
> linker then also eliminates any side effects of the initialization.
> This might cause problems in some cases when the side effect is
> expected. The problem is strongly related to static linking. I
> couldn't observe it when linking the object files directly into an
> executable or in a shared library. This inconsistency is also
> problematic.
>
> Example 1: The side effect is used to register an algorithm by name
> that can be created without knowing the concrete type later ("self
> registering factory").
> https://godbolt.org/z/YTqEW7
>
> Example 2: Many C-Libraries need an explicit call to an init function
> before the library is usable. A common solution is to do this
> statically at one place, so it can't be forgotten.
>
> Alternatives to get the above example working with static linking:
> - Explicitly do the registration and do not rely on static
> initialization side effects.
> - Write this code by hand.
> - Perform a mock step to generate the registration code.
> - Use platform dependent linker flags to completely disable removal of
> unused symbols.
> - Trick the optimizer to include the unused symbols (Hacks):
> - Add unnecessary includes.
> - Place the initialization statement inside a header file.
> - Dummy access to static variables so the linker is not allowed to
> remove them.
> - Bugusing
>
> Possible solutions to guarantee code execution before entering main():
> - Add an attribute for (static) variables that should not be discarded
> by the linker. e.g. [[nodiscard]] or [[keep]]
> - No impact on existing code as it adds a new attribute that is
> optional. It also does not alter the default behavior.
> [[keep]] const auto MyUnusedVariable = InitializeSomeLibrary(); //
> This happens in global scope.
>
> - prevent the linker from removing static variables which have an
> initializer with a side effect.
> - Might be impossible to detect.
> - Could have a performance impact on existing codebases.
>
> - add a general construct to execute code before entering main(), so
> the user is no longer required to fake initialize with dummy variables
> and side effects.
> - Syntactic sugar for the lambda initializer combined with an
> execution guarantee.
> - The problem still exists. There is just another syntax to
> circumnavigate it.
> initialize
> {
> const auto MyUnusedVariable = InitializeSomeLibrary();
> }
>
> It might also be a good idea to warn when the linker throws away
> symbols with side effects (Which might be impossible to detect in some
> cases).
>
> Regards,
> Konstantin Harmuth
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2020-12-21 06:12:21