在使用 gdb 调试 C++ 代码时,如何通过索引获得特定的 std::map 值?

How can I get specific std::map value with indexing while using gdb for debuggin c++ code?

我使用 Ubuntu 20.04-LTS 和 WSL(Windows 子系统 Linux),GDB 版本是 9.2,我用 c++11 构建了我的 c++ 代码。

我试图通过 GDB 中的索引访问 std::map 的值,但是 GDB 显示错误消息“无效转换”。

下面我的代码是一样的

#include <iostream>
#include <map>
#include <string>

using std::cout;
using std::map;
using std::string;
using std::to_string;

int main()
{
    map<string, int> si;

    for(int i = 0; i < 10; ++i)
    {
        si[to_string(i)] = i;
    }

    for(int i = 0; i < 10; ++i)
    {
        cout << si[to_string(i)] << "\n";
    }
}

并且,在 GDB 中

GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ctest...
(gdb) l main
6       using std::map;
7       using std::string;
8       using std::to_string;
9
10      int main()
11      {
12              map<string, int> si;
13
14              for(int i = 0; i < 10; ++i)
15              {
(gdb) l 15
10      int main()
11      {
12              map<string, int> si;
13
14              for(int i = 0; i < 10; ++i)
15              {
16                      si[to_string(i)] = i;
17              }
18
19              for(int i = 0; i < 10; ++i)
(gdb) b 18
Breakpoint 1 at 0x2579: file ctest.cpp, line 19.
(gdb) r
Starting program: /home/lksj/ctest

Breakpoint 1, main () at ctest.cpp:19
19              for(int i = 0; i < 10; ++i)
(gdb) p si["1"]
Invalid cast.
(gdb)

如何在 GDB 中直接使用索引访问 std::map 对象值?

您首先在“.gdbinit”文件中编写以下代码。

define newstr
set ($arg0)=(std::string*)malloc(sizeof(std::string))
call ($arg0)->basic_string()
# 'assign' returns *this; casting return to void avoids printing of the 
struct.
call (void)( ($arg0)->assign($arg1) )
end

define delstr
call ($arg0)->~basic_string(0)
#                           ^
call free($arg0)
set ($arg0)=(void*)0
end

然后在您的 C++ 代码中编写以下函数。

void indexing_map( map<string,[type]> & m, string i )
{
    cout << m[i] << "\n";
}

现在,万事俱备。您只需执行 gdb 以使用

调试您的代码
newstr $foo [any string of map of the key]

例如,

example.cpp

#include <iostream>
#include <unordered_map>
#include <string>

using std::cout;
using std::unordered_map;
using std::string;

void indexing_map(unordered_map<string, int> &m, string i)
{
   cout << m[i] << "\n";
}

int main()
{
    unordered_map<string, int> st_in;
    st_in["1"] = 1;
    st_in["2"] = 2;
    st_in["3"] = 3;

    indexing_map(st_in, "1");

    return 0;
}

和 gdb

(gdb) b 25
Breakpoint 1 at 0x28d6: file ctest.cpp, line 25.
(gdb) r
Starting program: /home/user/ctest
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main () at ctest.cpp:25
25          st_in["3"] = 3;
(gdb) newstr $foo "1"
(gdb) call indexing_map(st_in , *$foo)
1