Supposed that there is a base class and two derived classes, the base class has a pure virtual function named greeting(), both two derived classes inherit greeting() from the base class and implement their own greeting() respectively.
Then there is a std::map<std::string, Base*> obj_map which stores the object names and the corresponding address.
Now I am getting the object pointer through obj_map by given object name, then use -> to call greeting().
The problem is that, if I step into the line using gdb when obj_map["..."]->greeting() is called, gdb cannot stop at the greeting() of derived class, but at operator[](key_type&& __k) of std::map.
/*
* @Author: dylan
* @Date: 2022-09-08 01:09:20
* @LastEditTime: 2022-09-08 01:18:34
* @LastEditors: dylan
* @Description:
* @FilePath: /cpptest/debug-derived-virtual-function/main.cc
*/
#include <iostream>
#include <string>
#include <map>
class Base {
public:
Base(const std::string &obj_name) : name(obj_name) { }
virtual void greeting() = 0;
protected:
std::string name;
};
class Derived_1 : public Base {
public:
Derived_1(const std::string &obj_name) : Base(obj_name) { }
void greeting() override {
std::cout << "Hello, I am " << name << "!" << std::endl;
}
};
class Derived_2 : public Base {
public:
Derived_2(const std::string &obj_name) : Base(obj_name) { }
void greeting() override {
std::cout << "Bonjour, c'est " << name << "!" << std::endl;
}
};
int main()
{
Derived_1 derived_1("Ben");
Derived_2 derived_2("Anaise");
std::map<std::string, Base*> obj_map;
obj_map["Ben"] = &derived_1;
obj_map["Anaise"] = &derived_2;
obj_map["Ben"]->greeting();
obj_map["Anaise"]->greeting();
return 0;
}
Execute g++ -g3 -Wall -O0 main.cc -o main to compile.
The debug information is below:
(gdb)
41
42 std::map<std::string, Base*> obj_map;
43
44 obj_map["Ben"] = &derived_1;
45 obj_map["Anaise"] = &derived_2;
46
47 obj_map["Ben"]->greeting();
48 obj_map["Anaise"]->greeting();
49
50 return 0;
(gdb) break 47
Breakpoint 1 at 0x25c2: file main.cc, line 47.
(gdb) run
Starting program: /home/ubuntu/workspace/practice/cpptest/debug-derived-virtual-function/main
Breakpoint 1, main () at main.cc:47
47 obj_map["Ben"]->greeting();
(gdb) step
std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, Base*, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, Base*> > >::operator[] (
this=0x7fffffffdda0, __k=...) at /usr/include/c++/9/bits/stl_map.h:510
510 operator[](key_type&& __k)
(gdb) n
515 iterator __i = lower_bound(__k);
(gdb)
517 if (__i == end() || key_comp()(__k, (*__i).first))
(gdb)
521 return (*__i).second;
(gdb)
522 }
(gdb)
Hello, I am Ben!
main () at main.cc:48
48 obj_map["Anaise"]->greeting();
(gdb) step
std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, Base*, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, Base*> > >::operator[] (
this=0x7ffff7c393c6 <__GI__IO_fflush+134>, __k=...) at /usr/include/c++/9/bits/stl_map.h:510
510 operator[](key_type&& __k)
(gdb) n
515 iterator __i = lower_bound(__k);
(gdb)
517 if (__i == end() || key_comp()(__k, (*__i).first))
(gdb)
521 return (*__i).second;
(gdb)
522 }
(gdb)
Bonjour, c'est Anaise!
main () at main.cc:50
50 return 0;
(gdb)
As you can see, the gdb did not step into the corresponding greeting() of each derived class.
So is it possible to let gdb step into the corresponding greeting() correctly?
APPEND: I am working on non-small project, every time I compile the project will take a lot of time. Is there any way can work without modifying the code? Maybe there are over 200 derived classes like this, so it's quite a hassle to figure out which function was actually called each time.