我在c ++程序中遇到了一个奇怪的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() );
}
输出:
% 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
现在运行正常。我从B b_
删除b_
({1}}声明),保存a.hpp
(触发构建)并再次运行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 clean
,则程序运行时不会出现段错误。如果删除了类中的成员并且构建了没有干净的项目,请帮助我理解为什么程序会出现段错误。
答案 0 :(得分: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 A
(a.o
)的新对象文件将使用较新的定义,因此崩溃。
(具体来说,新的class A
具有不同的大小,因此它需要在main()
中的堆栈上保留的内存是不同的,并且其成员变量的配置也不同。)
这显然是Makefile
中依赖错误的问题。
当您运行make clean/make
时,所有文件都会使用class A
相同的正确定义,一切都会正常运行。