段错误的好奇案例

Vik*_*kas 5 c++ segmentation-fault

我在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;
Run Code Online (Sandbox Code Playgroud)

a.cpp

#include "a.hpp"
A::A () {}
Run Code Online (Sandbox Code Playgroud)

b.hpp

#pragma once
#include <string>

class B
{   
    public:
        B ();
    private:
        std::string str1_;
};   
Run Code Online (Sandbox Code Playgroud)

b.cpp

#include "b.hpp"    
B::B () {}
Run Code Online (Sandbox Code Playgroud)

main.cpp中

#include "a.hpp"

int main ()
{
    A_ptr a( new A() );
}
Run Code Online (Sandbox Code Playgroud)

make的输出:

% 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
Run Code Online (Sandbox Code Playgroud)

现在运行正常.我删除B b_(声明b_)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
Run Code Online (Sandbox Code Playgroud)

现在编写段错误:

(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
Run Code Online (Sandbox Code Playgroud)

如果我make cleanmake,然后程序运行没有segfault.请帮助我理解为什么程序段错误,如果一个成员被删除并且项目是在没有干净的情况下构建的.

ser*_*gio 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
Run Code Online (Sandbox Code Playgroud)

你正在重新编译a.cpp.然后链接到上一次make运行中生成的其余目标文件.这将main.cpp使用class A(包含在a.h)的旧定义,而class A(a.o)的新对象文件将使用更新的定义,因此崩溃.

(具体来说,new class A具有不同的大小,因此需要在堆栈中保留的内存main()是不同的,并且其成员变量的配置也不同).

这显然是你的依赖错误的问题Makefile.

当您运行时make clean/make,所有文件将使用相同,正确的定义class A,一切都将正常工作.