Vikas
Vikas

Reputation: 8948

Curious case of segfault

I faced a weird case of segfault in a c++ program. I'm able to reproduce it in a small code, but don't understand why is it happening. Here is the code:

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

Output of 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

Now this runs fine. I remove B b_ (declaration of b_) from a.hpp, save a.cpp (to trigger a build) and run make again:

% 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

And now program segfaults with:

(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

And if I make clean and make, then program runs without segfault. Please help me understand why program segfaults if a member from class is removed and project is built without clean.

Upvotes: 6

Views: 1683

Answers (1)

sergio
sergio

Reputation: 69027

On your second run of 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

you are recompiling just a.cpp. Then linking to the rest of object files produced in the previous run of make. This will make main.cpp use the older definition of class A (contained in a.h), while the new object file for class A (a.o) will use the newer definition, hence the crash.

(Concretely, new class A has different size, so the memory it needs to be reserved on the stack in main() is different and the disposition of its member variables is also different).

This is clearly a problem of faulty dependencies in your Makefile.

When you run make clean/make, all the files will use the same, correct definition for class A and everything will work out correctly.

Upvotes: 11

Related Questions