Question

The compiler generates some class methods like copy constructors, destructors, etc. Is it possible to have gdb break on those methods to, e.g., observe where objects are being copied or destroyed?

Was it helpful?

Solution

Can gdb break on implicit class methods?

Yes, of course, it can.

(gdb) break MyClass::MyClass(const MyClass &)     // break when copied
(gdb) break MyClass::~MyClass()                   // break when object destroyed

as simple as that. These are breakpoints based, NOT on file:line, but on function names. If you've a namespace wrapping the class then make sure you give the fully qualified name for it e.g.

(gdb) break NyNamespace::MyClass::MyClass(const MyClass &)

Look here for a list of ways to specify breakpoints in GDB.

OTHER TIPS

gdb can break on anything that is either mentioned in the debuginfo or as an ELF sybmol. Offhand I do not know whether your compiler emits debuginfo for these artificial methods.

I have similar needs, I built my code with

g++ main.cpp -std=c++1y -o app_name -g -ggdb

but gdb can't see my implict constructors and assignment operators symbols. And for this reason it don't break on them. Because of that I've used this hack to be able to break on implicitly defined methods of examined class: just implement your own class with explicitly defined methods you're interesting in. Then add this new class object as data member of class you want to debug. Set breakpoints on methods of new class. Enjoy!

Example:

class LifeCycleInspector
{
public:
    LifeCycleInspector()
    {
        printf( "Default C-tor\n" );
    }

    LifeCycleInspector( const LifeCycleInspector& )
    {
        printf( "Copy C-tor\n" );
    }

    LifeCycleInspector( LifeCycleInspector&& )
    {
        printf( "Move C-tor\n" );
    }

    LifeCycleInspector& operator=( const LifeCycleInspector& )
    {
        printf( "Copy A-ment\n" );
        return *this;
    }

    LifeCycleInspector& operator=( LifeCycleInspector&& )
    {
        printf( "Move A-ment\n" );
        return *this;
    }

    virtual ~LifeCycleInspector()
    {
        printf( "D-tor\n" );
    }
};

class Test
{
private:
    LifeCycleInspector lci_;
};

void foo()
{
    Test t1;
    Test t2( t1 );
    Test t3;
    t3 = t1;
    Test t4( std::move( t3 ) );
    Test t5;
    t5 = std::move( t4 );
}

int main()
{
    foo();

    return 0;
}

Output sample:

Default C-tor
Copy C-tor
Default C-tor
Copy A-ment
Move C-tor
Default C-tor
Move A-ment
D-tor
D-tor
D-tor
D-tor
D-tor

Important! If you make your methods empty, like:

LifeCycleInspector( const LifeCycleInspector& )
{   
}

- your compiler optimization may do fancy things and your debug output may be pretty strange. In this case you may add some routine to the methods to prevent optimization. Also you should move methods implementation from class to its header or source, as defining method right in class's body is implicitly making this method an candidate for inlining. gdb will not break on inlined methods because they usually have no definition which could be adressed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top