【问题标题】:Curious case of segfault段错误的奇怪案例
【发布时间】:2012-10-17 21:06:40
【问题描述】:

我在一个 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 () {}

ma​​in.cpp

#include "a.hpp"

int main ()
{
    A_ptr a( new A() );
}

ma​​ke的输出

% 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,那么程序运行时不会出现段错误。请帮助我理解如果类中的成员被删除并且项目在没有清理的情况下构建,为什么程序段错误。

【问题讨论】:

    标签: c++ segmentation-fault


    【解决方案1】:

    在您第二次运行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 定义,并且一切都会正常运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多