2012-10-17 9 views
5

Napotkałem dziwny przypadek segfault w programie C++. Mogę go odtworzyć w małym kodzie, ale nie rozumiem, dlaczego tak się dzieje. Oto kod:Ciekawy przypadek segfaulta

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()); 
} 

Wyjście zrobić:

% 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 

Teraz to działa dobrze. Usunąć B b_ (Deklaracja b_) z a.hpp zapisz a.cpp (aby wyzwolić kompilacji) i uruchomić make ponownie:

% 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 

a teraz naruszenia ochrony pamięci programu z:

(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 

A gdybym make clean i make , a następnie program działa bez segfault. Proszę pomóż mi zrozumieć, dlaczego program ulega awarii, jeśli członek z klasy zostanie usunięty, a projekt zostanie zbudowany bez czystej.

Odpowiedz

10

Na drugim biegu 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 

jesteś rekompilacji tylko a.cpp. Następnie łączenie z pozostałymi plikami obiektowymi wyprodukowanymi w poprzednim uruchomieniu make. To sprawi main.cpp używać starszej definicji class A (zawartego w a.h), podczas gdy nowy plik obiektowy dla class A (a.o) użyje nowszej definicji, stąd katastrofę.

(Konkretnie, nowe class A ma inną wielkość, tak pamięci musi zostać zarezerwowana na stosie w main() jest inny i układ jego zmiennych składowych jest inaczej).

To jest wyraźnie problem wadliwych zależności w twoim Makefile.

Po uruchomieniu make clean/make, wszystkie pliki będą korzystać z tego samego, poprawną definicję class A i wszystko będzie działać poprawnie.

Powiązane problemy