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
std::logic_error - Initialization Order Fiasco #229
Conversation
Unitialized rules can silently be aggregated during parser composition, because of statics across translation units. Also add a debug assert diagnosing this situation. See http://stackoverflow.com/a/41785268/85371 for the reproducer/analysis.
Unitialized rules can silently be aggregated during parser composition, because of statics across translation units. get_info<> has been fixed so it doesn't break. As a QoI measure, it also added a debug assert to help diagnose the situation. In unary_parser and binary_parser, this commit allows that debug assert to run as early as possible (typically during program startup) so that users will notice the initialization ordering problem. See http://stackoverflow.com/a/41785268/85371 for the reproducer/analysis.
Hmmm... Tricky. Let me analyze this some more. |
OK, there should be a better way to solve this, but for now, I think this is a good intermediate step. |
I'm wondering if we should add this assert_initialized_rule in the second commit 16320a5. If the coding style is bad and with 50% chance it will trigger the Static Initialization Order Fiasco (SIOF) in debug build. But even if it does not trigger SIOF in debug build (also with 50% chance), it could still trigger SIOF in release build and we know nothing about that. Most x3 parsers could have constexpr constructor (I'm trying to do this now). But this assert_initialized_rule cannot be constexpr and it makes all derived classes of unary_parser/binary_parser cannot have constexpr constructor. Can we reconsider the solution here? |
@wanghan02 I am sorry I do not understand your issue. Hopefully, rule placeholders SIOF will no cause a real problem unless you are enabling
AFAIK you can use |
Thanks for the information. I still have some questions.
Then why don't we wrap it with BOOST_SPIRIT_DEBUG instead of NDEBUG?
|
I am not sure if I have time to look into this now, but as I said above, I'm hoping to have a better solution. One thing I really want to do is remove the need for the |
OK, I'll have another look today. |
Because
Short answer is: the check is needed to cover cases that cannot be resolved at compile time.
Why you are initializing a 'big parser' in a function? If it has to be constructed dynamically (because of something is known at run-time) constexpr constructors will not solve your problem.
I would vote for it back then, but since C++20 will have constexpr |
I agree that constexpr cannot solve all the problems. But in my opinion, it does bring many benefits. If most of the parser/rules can be constexpr, then why not? What I propose is, we use another macro other than NDEBUG for this run time check. Then it's the user's decision to choose between this run time check and constexpr. |
The check, as is, should not interfere with your constexpr things. Please open an issue with a code sample that show the actual problem. |
@Kojoley Have you read the code? The check calls
|
Sure, but we'll still have to deal with c++17 for a long time. |
(reported by Exagon http://stackoverflow.com/a/41785268/85371)
Due to Static Initialization Order Fiasco sometimes X3 parsing aborts with a
std::logic_error
. The cause is unitializedrule::name
fields.It is clear that the design of Spirit X3 has accounted for static initialization order in that the
parse_rule
specializations contain function-local instances that defeat the issue.However, the rule name initialization lives inside the namespace-scope static variable and its initialization is not guarded. This is probably an oversight.
Unfortunately I don't think there is a clean/elegant solution that will not introduce more function-local statics (with their syntax and runtime overhead).
This PR adds diagnostics to detect when a rule was copied before its initialization. The commit comments and code detail the approach.