2012-10-17 12 views
5

Ich hatte einen seltsamen Fall von segfault in einem C++ - Programm. Ich bin in der Lage, es in einem kleinen Code zu reproduzieren, verstehe aber nicht, warum es passiert. Hier ist der Code:Seltsamer Fall von segfault

a.hpp:

#pragma once 
#include <boost/shared_ptr.hpp> 
#include "b.hpp" 

class A 
{ 
    public: 
     explicit A();  
    private: 
     std::string str1_; 
     B b_; 
     std::string str2_; 
}; 

typedef boost::shared_ptr<A> A_ptr; 

a.cpp

#include "a.hpp" 
A::A() {} 

b.hpp

#pragma once 
#include <string> 

class B 
{ 
    public: 
     B(); 
    private: 
     std::string str1_; 
}; 

b.cpp

#include "b.hpp"  
B::B() {} 

main.cpp

#include "a.hpp" 

int main() 
{ 
    A_ptr a(new A()); 
} 

Ausgabe machen:

% make 
g++ -Wall -Wextra -g -fno-inline -O0 -c -o main.o main.cpp 
g++ -Wall -Wextra -g -fno-inline -O0 -c -o a.o a.cpp 
g++ -Wall -Wextra -g -fno-inline -O0 -c -o b.o b.cpp 
g++ -o main main.o a.o b.o 
dsymutil main 

Jetzt läuft das in Ordnung. Ich entferne B b_ (Erklärung b_) aus a.hpp, speichern a.cpp (ein Build auslösen) und führen make wieder:

% make 
g++ -Wall -Wextra -g -fno-inline -O0 -c -o a.o a.cpp 
g++ -o main main.o a.o b.o 
dsymutil main 

Und jetzt Programm segfaults mit:

(gdb) bt 
#0 0x00007fff97f106e5 in std::string::_Rep::_M_dispose() 
#1 0x00007fff97f10740 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() 
#2 0x0000000100001091 in A::~A (this=0x1001008b0) at a.hpp:8 
#3 0x00000001000011da in boost::checked_delete<A> (x=0x1001008b0) at checked_delete.hpp:34 
#4 0x0000000100001026 in boost::detail::sp_counted_impl_p<A>::dispose (this=0x1001008d0) at sp_counted_impl.hpp:78 
#5 0x0000000100000d9a in boost::detail::sp_counted_base::release (this=0x1001008d0) at sp_counted_base_gcc_x86.hpp:145 
#6 0x0000000100000dd4 in boost::detail::shared_count::~shared_count (this=0x7fff5fbff568) at shared_count.hpp:305 
#7 0x0000000100000f2b in boost::shared_ptr<A>::~shared_ptr (this=0x7fff5fbff560) at shared_ptr.hpp:159 
#8 0x0000000100000aac in main() at main.cpp:5 

Und wenn ich make clean und make , dann läuft das Programm ohne segfault. Bitte helfen Sie mir zu verstehen, warum Programme segfolds, wenn ein Mitglied aus der Klasse entfernt wird und das Projekt ohne sauber erstellt wird.

Antwort

10

Auf dem zweiten Lauf von make:

% make 
g++ -Wall -Wextra -g -fno-inline -O0 -c -o a.o a.cpp 
g++ -o main main.o a.o b.o 
dsymutil main 

Sie sind neu zu kompilieren nur a.cpp. Anschließend Verknüpfung mit dem Rest der Objektdateien, die im vorherigen make-Lauf erstellt wurden. Dadurch wird main.cpp die ältere Definition von class A (in a.h enthalten) verwendet, während die neue Objektdatei für class A (a.o) die neuere Definition verwendet, daher der Absturz.

(Konkret, neue class A hat unterschiedliche Größe, so dass der Speicher, der auf dem Stapel in main() reserviert werden muss, anders ist und die Anordnung seiner Mitgliedsvariablen ebenfalls unterschiedlich ist).

Dies ist eindeutig ein Problem von fehlerhaften Abhängigkeiten in Ihrem Makefile. Wenn Sie make clean/make ausführen, verwenden alle Dateien die gleiche, korrekte Definition für class A und alles wird korrekt funktionieren.