2016-05-02 10 views
3

Kann jemand helfen, die folgenden seg fautl verstehen, und warum auch funktioniert es auf die Änderung der Link bestellen:seg Fehler bei der Verwendung von globalen Objekt statisches Element

common.h Datei:

#include <set> 
struct T { 
    explicit T(const char*) { 
     Instances.insert(this); 
    } 
    static std::set<T*> Instances; 
}; 

d. cc-Datei:

#include "common.h" 
T d(__FILE__); 

main.cc Datei:

#include "common.h" 
#include <set> 
#include <iostream> 

/*static*/ std::set<T*> T::Instances; 
int main() { 
    std::cout << "T::Instances.size() = " << T::Instances.size() << std::endl; 
    while(true); 
} 

Gebäude und läuft mit folgenden Befehlen:

g++ -c -g -Wall -Wextra d.cc -o d.o 
g++ -c -g -Wall -Wextra main.cc -o main.o 
g++ -g d.o main.o -o app 

./app

die Befehle ausführen ich einen seg Fehler erhalten, mit folgenden Backtrace:

$ ./app 
Segmentation fault (core dumped) 
$ gdb ./app 
(gdb) run 
Starting program: /home/meodou/zdev/poc_at_7405/testi/app 
Program received signal SIGSEGV, Segmentation fault. 
0x00007ffff7afebca in std::local_Rb_tree_decrement (__x=0x6031e8 <T::Instances+8>) at ../../../../../libstdc++-v3/src/c++98/tree.cc:98 
98   && __x->_M_parent->_M_parent == __x) 
(gdb) bt 
#0 0x00007ffff7afebca in std::local_Rb_tree_decrement (__x=0x6031e8 <T::Instances+8>) at ../../../../../libstdc++-v3/src/c++98/tree.cc:98 
#1 0x0000000000401365 in std::_Rb_tree_iterator<T*>::operator-- (this=0x7fffffffdc50) at /usr/include/c++/5.3.1/bits/stl_tree.h:220 
#2 0x000000000040102f in std::_Rb_tree<T*, T*, std::_Identity<T*>, std::less<T*>, std::allocator<T*> >::_M_get_insert_unique_pos (
this=0x6031e0 <T::Instances>, [email protected]: 0x6031d1 <d>) at /usr/include/c++/5.3.1/bits/stl_tree.h:1819 
#3 0x0000000000400dfe in std::_Rb_tree<T*, T*, std::_Identity<T*>, std::less<T*>, std::allocator<T*> >::_M_insert_unique (this=0x6031e0 <T::Instances>, 
[email protected]: 0x6031d1 <d>) at /usr/include/c++/5.3.1/bits/stl_tree.h:1863 
#4 0x0000000000400d79 in std::set<T*, std::less<T*>, std::allocator<T*> >::insert (this=0x6031e0 <T::Instances>, [email protected]: 0x6031d1 <d>) 
at /usr/include/c++/5.3.1/bits/stl_set.h:485 
#5 0x0000000000400d47 in T::T (this=0x6031d1 <d>) at common.hh:6 
#6 0x0000000000400ce0 in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at d.cc:2 
#7 0x0000000000400d0a in _GLOBAL__sub_I_d() at d.cc:2 
#8 0x0000000000401b2d in __libc_csu_init() 
#9 0x00007ffff71a050f in __libc_start_main (main=0x40173b <main()>, argc=1, argv=0x7fffffffdf68, init=0x401ae0 <__libc_csu_init>, fini=<optimized out>, 
rtld_fini=<optimized out>, stack_end=0x7fffffffdf58) at libc-start.c:245 
#10 0x0000000000400bc9 in _start() 

Damit etwas, was ich versuche, verstehen. Die zweite Sache ist, dass, wenn ich die Verknüpfung Reihenfolge umkehren:

From g++ -g d.o main.o -o app 
To g++ -g main.o d.o -o app 

Das Programm ohne seg Fehler läuft.

$ g++ -c -g -Wall -Wextra d.cc -o d.o 
$ g++ -c -g -Wall -Wextra main.cc -o main.o 
$ g++ -g main.o d.o -o app 
$ ./app 
T::Instances.size() = 1 

Jede Erklärung, was das funktioniert? Das Problem scheint mit der Initialisierung der globalen Variablen zusammenzuhängen, aber ich kann immer noch nicht sehen, was passiert.

Verwenden g ++ (GCC) 5.3.1

BR,

...........................

In Antwort auf Quentin Kommentar: Ja, ich weiß, dass sollte mit der statischen Initialisierung verbunden sein, aber ich sehe nicht wirklich, wie dies geschieht. (Ich bin nicht im Fall von https://isocpp.org/wiki/faq/ctors#static-init-order, wo eine Kompiliereinheit ein Objekt nicht initialisiert, wie es in einer anderen Kompiliereinheit gefunden wird, zumindest nicht direkt).

ich auch ein T-Objekt die main.cc Datei hinzufügen:

#include <iostream> 
/*static*/ std::set<T*> T::Instances; 
+T main_obj(__FILE__); 
int main() { 
std::cout << "T::Instances.size() = " << T::Instances.size() << std::endl; 

ich noch ein Absturz kommen werde, hier mein Verständnis ist, dass wir eine statische Funktion auf einem Objekt aufrufen, die wir haben bereits in aktuelle Kompiliereinheit (sollte korrekt initialisiert werden). Wir sind also nicht direkt von dem in der d.cc-Datei gefundenen Objekt abhängig. Wieder glaube ich fest, dass es sich um statische Initialisierung handelt, aber ich sehe nicht klar die Erklärung davon. (Das Objekt, das wir sein statisches Element aufrufen sollte bereits initialisiert werden)

+2

Sie wurden von dem [Statischen Initialisierungsauftrag Fiasko] (https://isocpp.org/wiki/faq/ctors#static-init-order) gebissen. – Quentin

Antwort

0

Sie static std::set<T*> Instances; in d.cc definieren sollten:

#include "common.h" 
#include <set> 
std::set<T*> T::Instances; 
T d(__FILE__); 

und entferne sie aus main.cc.

+0

Offenbar möchte OP ein 'T' in jeder von mehreren' cc' Dateien instanziieren - Ihre Lösung wird nur für eine funktionieren. – Quentin

+0

@quentin Das stimmt, ich habe nur das aktuelle Szenario berücksichtigt. –

+0

Ja ... Ich möchte es in mehreren Dateien haben. Die Änderung, die Sie vorgeschlagen haben, macht das Problem zu verschwinden, aber mir fehlt es zu verstehen, was hier passiert, können Sie bitte weitere Informationen geben? – meodou

Verwandte Themen