diff options
author | Andres Noetzli <andres.noetzli@gmail.com> | 2018-08-11 11:13:17 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-11 11:13:17 -0700 |
commit | b62055f1204a0846eef728b2b62e5fc77df4048c (patch) | |
tree | 41fe58fb6a5f3dd5815785304990282c6a3abefc /src/expr/attribute_internals.h | |
parent | 8a8d65e2fddf88bfbd6cc67d8738510feaea05e6 (diff) |
Make attributes robust to static init orderings (#2295)
@taking pointed out that part of the issue fixed in #2293 is also that
we should be more robust to different (de-)initialization orders. A
common, portable way to achieve this is to allocate the object in
question on the heap and make the pointer to it static [0]. This commit
fixes the variable in question.
I have tested this fix in ASAN (without using --no-static-init flag for
CxxTest) and it works.
[0] https://isocpp.org/wiki/faq/ctors#construct-on-first-use-v2
Diffstat (limited to 'src/expr/attribute_internals.h')
-rw-r--r-- | src/expr/attribute_internals.h | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/src/expr/attribute_internals.h b/src/expr/attribute_internals.h index 51116963d..c21b15140 100644 --- a/src/expr/attribute_internals.h +++ b/src/expr/attribute_internals.h @@ -505,8 +505,19 @@ template <class T, bool context_dep> struct AttributeTraits { typedef void (*cleanup_t)(T); static std::vector<cleanup_t>& getCleanup() { - static std::vector<cleanup_t> cleanup; - return cleanup; + // Note: we do not destroy this vector on purpose. Instead, we rely on the + // OS to clean up our mess. The reason for that is that we need this vector + // to remain initialized at least as long as the ExprManager because + // ExprManager's destructor calls this method. The only way to guarantee + // this is to never destroy it. This is a common idiom [0]. In the past, we + // had an issue when `cleanup` wasn't a pointer and just an `std::vector` + // instead. CxxTest stores the test class in a static variable, which could + // lead to the ExprManager being destroyed after the destructor of the + // vector was called. + // + // [0] https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use + static std::vector<cleanup_t>* cleanup = new std::vector<cleanup_t>(); + return *cleanup; } }; |