2012-10-17 67 views
5

我在C++程序中遇到了一个奇怪的段错误。我可以用小代码重现它,但不明白为什么会发生。下面是代码:段错误的好奇案例

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

输出:

% 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 

现在这个运行良好。我从a.hpp删除B b_(的b_声明),保存a.cpp(触发生成),然后再次运行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 

现在程序段错误:

(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 

如果我make cleanmake ,然后程序运行时没有段错误。请帮我理解为什么程序段错误,如果一个类的成员被删除和项目建成没有干净。

回答

10

在您的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 

你重新编译只是a.cpp。 然后链接到make的上一次运行中生成的其余对象文件。这将使main.cpp使用class A(包含在a.h中)的旧定义,而class Aa.o)的新对象文件将使用更新的定义,因此会导致崩溃。 (具体来说,新的class A具有不同的大小,因此它需要在堆栈中保留的内存在main()中是不同的,并且其成员变量的配置也不同)。

这显然是您的Makefile存在错误依赖关系的问题。

当您运行make clean/make时,所有文件将使用class A相同的正确定义,并且所有内容都能正常工作。