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, , , .