2012-10-17 11 views
5

Ho affrontato un caso strano di segfault in un programma C++. Sono in grado di riprodurlo in un piccolo codice, ma non capisco perché sta succedendo. Ecco il codice:Curioso caso di 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()); 
} 

uscita di rendere:

% 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 

Ora, questo funziona bene. Rimuovo B b_ (dichiarazione di b_) da a.hpp, salvo a.cpp (per innescare una build) ed eseguire make ancora:

% 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 

E ora segfaults di programma con:

(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 

E se io make clean e make , quindi il programma viene eseguito senza segfault. Per favore aiutami a capire perché programma segfaults se un membro di classe viene rimosso e il progetto viene creato senza pulizia.

risposta

10

Sul secondo run di 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 

state ricompilando solo a.cpp. Quindi il collegamento al resto dei file oggetto prodotti nella precedente esecuzione di make. Questo farà sì che main.cpp utilizzi la precedente definizione di class A (contenuta in a.h), mentre il nuovo file oggetto per class A (a.o) utilizzerà la definizione più recente, quindi l'arresto anomalo.

(Concretamente, il nuovo class A ha dimensioni diverse, quindi la memoria che deve essere riservata nello stack in main() è diversa e anche la disposizione delle sue variabili membro è diversa).

Questo è chiaramente un problema di dipendenze difettose nel telefono Makefile.

Quando si esegue make clean/make, tutti i file utilizzeranno la stessa definizione corretta per class A e tutto funzionerà correttamente.

Problemi correlati