Can gdb break on implicit class methods?
Asked Answered
S

3

11

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?

Singleaction answered 3/4, 2014 at 19:36 Comment(2)
You can break on the constructors / destructors of the types of the membersGhastly
Often, and in the case I'm looking at now, all the members also have implicitly defined {copy,move} constructors/destructors.Singleaction
D
9

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.

Dispersive answered 4/4, 2014 at 17:40 Comment(5)
Using gdb 7.5.1 and gcc 4.7.2 and compiling with -ggdb, I find that setting the breakpoints on the implicit methods sets a breakpoint on the line that defines the class. Interestingly, if I set a breakpoint at that file:lieno, gdb asks me which breakpoint I want to set, giving me a choice of all the implicitly defined methods!Singleaction
odd that it doesn't work for me. gdb did set a breakpoint (at 3 locations?) when I asked it to break at boost::asio::detail::task_io_service::task_io_service(). Then, when I ran the program on top of gdb, I got errors like these "Cannot insert breakpoint 1. Error accessing memory address 0x11: Input/output error."Ertha
well, can this works on a template specialist class?Richert
@cli__ I tried this program locally with GCC 8.2.1 and GDB 8.2. It works. I gave b area<int> and r. It broke inside area, doing a bt showed that the first float variant call in main was skipped and it only broke into the int variant.Dispersive
For me it always fails here with Function "MyClass::MyClass(const MyClass&)" not defined. etc. I created a minimal main file, and also added a simple void ok() {} method to MyClass. Adding a breakpoint for ok works fine (via break MyClass::ok()). This is true even with all flags I can think of: -g -ggdb -O0.Alimentation
C
1

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.

Chuckhole answered 4/4, 2014 at 17:36 Comment(0)
B
0

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.

Boche answered 21/2, 2018 at 11:3 Comment(5)
"it is better to move methods implementation from header to source." Whether that is true is highly contextual. Also, adding a member adds memory overhead to the class it is added to, even if the object is empty, so while it's useful for debugging purposes, it could be very expensive if there are a very large number of objects of that type. Inheriting from it instead will allow for empty bass class optimizations.Manolete
thanks, what I meant, is that you should avoid to defining methods in class's body as this implicitly makes them candidates for inlining (same when you're using MyClass::MyClass() = default; definition outside you class's body - even if you've moved it to source file). and, unless you take an address of it, inlined method has no actual head/body, gdb can't break on it. it worth mentioning that EBO isn't working for multiple inheritance and that class with no data memory's footprint is usually like 1 char.Boche
What do you mean EBO "isn't working" for MI? godbolt.org/g/JHe1Gn Looks fine to me.Manolete
It must be 'EBO is generally not working for MI'. Source 'Effective C++ 3rd edition' : Item39’s observation that the EBO generally isn’t available under multiple inheritance is from David Vandevoorde’s and Nicolai M. Josuttis’ C++ Templates (Addison-Wesley, 2003).Boche
Well, then it's good to know we've made some progress in 15 years.Manolete

© 2022 - 2024 — McMap. All rights reserved.