{"id":162,"date":"2016-02-08T02:40:12","date_gmt":"2016-02-08T02:40:12","guid":{"rendered":"http:\/\/brucemyers.com\/?p=162"},"modified":"2020-09-15T14:37:15","modified_gmt":"2020-09-15T14:37:15","slug":"c-static-initialization-order-fiasco-workaround","status":"publish","type":"post","link":"https:\/\/brucemyers.com\/?p=162","title":{"rendered":"C++ Static Initialization Order Fiasco Workaround"},"content":{"rendered":"<p>The C++ Static Initialization Order Fiasco (SIOF) can happen when 2 classes have static initializers and one classes static initializer calls the other class before its static initializer has been executed. The order of static initializer execution is determined by the linker.<\/p>\n<h1>SIOF Example<\/h1>\n<p>A parser that stores some regexes.<\/p>\n<p>Parser.h<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nclass Parser {\nstatic std::map&lt;std::string, Regex&gt; regexs;\n}\n<\/pre>\n<p>Parser.cpp<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nusing namespace std;\nmap&lt;string, Regex&gt; Parser::regexs = {\n{\"table\" , Regex(\"!\\\\{\\\\|&#x5B;^{]*?\\\\|\\\\}!m\")},\n{\"link\" , Regex(\"!\\\\&#x5B;\\\\&#x5B;&#x5B;^\\\\&#x5B;\\\\]]*?\\\\]\\\\]!\")}\n};\n<\/pre>\n<p>Regex.h<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nclass Regex {\nstatic std::map&lt;char, int&gt; modifiers;\nRegex(string&amp; regex);\n}\n<\/pre>\n<p>Regex.cpp<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nusing namespace std;\nmap&lt;char, int&gt; Regex::modifiers {\n{'i', PCRE_CASELESS},\n{'m', PCRE_MULTILINE}\n};\n\nRegex::Regex(string&amp; regex) {\nmodifiers&#x5B;'m'] could fail\n}\n<\/pre>\n<p>Parser::regexes and Regex::modifers are both globally initialized statics.<\/p>\n<p>Depending on the linker, Parser::regexes could get initialized before Regex::modifers. If that happens, then the reference to modifiers['m'] will fail in the Regex constructor that the Parser::regexes initializer calls.<br \/>\n<!--more--><\/p>\n<h1>C++11 Workaround<\/h1>\n<p>Create a static unique_ptr to a map in a helper method.<\/p>\n<p>Regex.h<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nclass Regex {\nstd::unique_ptr&lt;std::map&lt;char, int&gt;&gt;&amp; getModTable();\nRegex(string&amp; regex);\n}\n<\/pre>\n<p>Regex.cpp<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nusing namespace std;\nunique_ptr&lt;map&lt;char, int&gt;&gt;&amp; Regex::getModTable()\n{\nstatic unique_ptr&lt;map&lt;char, int&gt;&gt; modifiers(new map&lt;char, int&gt;);\n\nif (! modifiers-&gt;empty()) return modifiers;\n\nmodifiers-&gt;insert(pair&lt;char,int&gt;('i', PCRE_CASELESS));\nmodifiers-&gt;insert(pair&lt;char,int&gt;('m', PCRE_MULTILINE));\n\nreturn modifiers;\n}\n\nRegex::Regex(string&amp; regex) {\nunique_ptr&lt;map&lt;char, int&gt;&gt;&amp; modifiers = getModTable();\nmodifiers&#x5B;'m'] will not fail\n}\n<\/pre>\n<p>Before the getModTable() method is executed for the first time, the locally initialized static unique_ptr is initialized to a new empty map. If the map is empty, then it is filled.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The C++ Static Initialization Order Fiasco (SIOF) can happen when 2 classes have static initializers and one classes static initializer calls the other class before its static initializer has been executed. The order of static initializer execution is determined by the linker. SIOF Example A parser that stores some regexes. Parser.h class Parser { static &hellip; <a href=\"https:\/\/brucemyers.com\/?p=162\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">C++ Static Initialization Order Fiasco Workaround<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[36],"tags":[],"class_list":["post-162","post","type-post","status-publish","format-standard","hentry","category-c"],"_links":{"self":[{"href":"https:\/\/brucemyers.com\/index.php?rest_route=\/wp\/v2\/posts\/162","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/brucemyers.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/brucemyers.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/brucemyers.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/brucemyers.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=162"}],"version-history":[{"count":14,"href":"https:\/\/brucemyers.com\/index.php?rest_route=\/wp\/v2\/posts\/162\/revisions"}],"predecessor-version":[{"id":192,"href":"https:\/\/brucemyers.com\/index.php?rest_route=\/wp\/v2\/posts\/162\/revisions\/192"}],"wp:attachment":[{"href":"https:\/\/brucemyers.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=162"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/brucemyers.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=162"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/brucemyers.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=162"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}