Repeating classic C ++ initialization order fiasco repetition

I recently encountered an unusual situation.

Consider the following class (place in header.h):

#ifndef HEADER_H
#define HEADER_H

#include <set>

template <class V, class T>
class Class
{
public:
    typedef std::set<const Class<V, T>* > instances_list;

    explicit Class(const V& Value):m_value(Value)
    {
    s_instances.insert(this);
    }
private:
    static instances_list s_instances;
    V m_value;
};

template <typename V, typename T>
typename Class<V,T>::instances_list Class<V,T>::s_instances;

class Something : public Class<int, Something>
{
public:
    static const Something SOMETHING_CONSTANT;

private:
    explicit Something(int value): Class<int, Something>(value)
    {}
};

#endif

and a very simple application using it:

#include "header.h"

const Something Something::SOMETHING_CONSTANT (1);

int main()
{
}

Compilation leads to varying degrees of success.

g ++ (4.9.2, 4.8.4 and 4.3.2) compiles the executable file, but they generate a SEGFAULT with a trace stack, for example:

#0  0x00007ffff7b4aaaa in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x00000000004012bb in std::_Rb_tree_iterator<Class<int, Something> const*>::operator-- (this=0x7fffffffdcf0) at /usr/include/c++/4.8/bits/stl_tree.h:204
#2  0x0000000000400ef2 in std::_Rb_tree<Class<int, Something> const*, Class<int, Something> const*, std::_Identity<Class<int, Something> const*>, std::less<Class<int, Something> const*>, std::allocator<Class<int, Something> const*> >::_M_get_insert_unique_pos (this=0x6030c0 <Class<int, Something>::s_instances>, __k=@0x7fffffffde08: 0x6030a4 <Something::SOMETHING_CONSTANT>) at /usr/include/c++/4.8/bits/stl_tree.h:1333
#3  0x0000000000400c1d in std::_Rb_tree<Class<int, Something> const*, Class<int, Something> const*, std::_Identity<Class<int, Something> const*>, std::less<Class<int, Something> const*>, std::allocator<Class<int, Something> const*> >::_M_insert_unique (this=0x6030c0 <Class<int, Something>::s_instances>, __v=@0x7fffffffde08: 0x6030a4 <Something::SOMETHING_CONSTANT>) at /usr/include/c++/4.8/bits/stl_tree.h:1377
#4  0x0000000000400b19 in std::set<Class<int, Something> const*, std::less<Class<int, Something> const*>, std::allocator<Class<int, Something> const*> >::insert (this=0x6030c0 <Class<int, Something>::s_instances>, 
    __x=@0x7fffffffde08: 0x6030a4 <Something::SOMETHING_CONSTANT>) at /usr/include/c++/4.8/bits/stl_set.h:463
#5  0x0000000000400ad9 in Class<int, Something>::Class (this=0x6030a4 <Something::SOMETHING_CONSTANT>, Value=@0x7fffffffde24: 1) at header.h:14
#6  0x0000000000400aa2 in Something::Something (this=0x6030a4 <Something::SOMETHING_CONSTANT>, value=1) at header.h:30
#7  0x0000000000400a24 in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at main.cpp:3
#8  0x0000000000400a6b in _GLOBAL__sub_I__ZN9Something18SOMETHING_CONSTANTE () at main.cpp:7
#9  0x00000000004015ed in __libc_csu_init ()
#10 0x00007ffff751ce55 in __libc_start_main (main=0x4009ed <main()>, argc=1, argv=0x7fffffffdf88, init=0x4015a0 <__libc_csu_init>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdf78) at libc-start.c:246
#11 0x0000000000400929 in _start ()

clang (3.4.1 and 3.5.0-10) create an executable file that works well, does not execute segfault.

Visual Studio 2015 creates a segfaulting application.

If I put everything in one file, then the compiler found on ideone.com ( http://ideone.com/Dhh8Hl ) creates a runtime error, signal 11.

I have a feeling, this behavior is undefined ... Please correct me if I'm wrong.

: ++ initalization ( fun ), , , g++ MSVC, clang.

(3.6.2) :

(3.7.1) (8.5) . POD (5.19); . , ; - . . , . . (.. ) . , . , . , .

, Static initialization shall be performed before any dynamic initialization takes place. , , const Something Something::SOMETHING_CONSTANT (1); (, , ), , . , , Other class template static data members (i.e., implicitly or explicitly instantiated specializations) have unordered initialization. , , , .

, https://isocpp.org/wiki/faq/ctors#static-init-order, , , .

+4
1

const Somthing SomeThing::SOMETHING_CONST(1);

: a const, , . . , const , ( . 5.19 [expr.const]).

, , constexpr. , std::set<int> , , constexpr.

. , , , , , . constexpr std::set<int>, .

+5

Source: https://habr.com/ru/post/1617401/


All Articles