Проверка содержимого стандартного контейнера (std :: map) с помощью gdb


93

Предположим, что есть что-то вроде этого:

#include <map>
int main(){
    std::map<int,int> m;
    m[1] = 2;
    m[2] = 4;
    return 0;
}

Я хотел бы иметь возможность проверить содержимое карты, запускающей программу из gdb.
Если я попробую использовать оператор индекса, я получу:

(gdb) p m[1]
Attempt to take address of value not located in memory.

Использование метода поиска не дает лучших результатов:

(gdb) p m.find(1)
Cannot evaluate function -- may be inlined

Есть ли способ добиться этого?


Чтобы напечатать все элементы без усечения больших карт: stackoverflow.com/questions/47743215/… Больше «Невозможно оценить функцию, возможно, встроено»: stackoverflow.com/questions/40633787/…
Ciro Santilli 郝海东 冠状 病 事件 法轮功

Ответы:


35

Я думаю, что нет, по крайней мере, если ваш источник оптимизирован и т.д. Однако есть несколько макросов для gdb, которые могут проверять контейнеры STL для вас:

http://sourceware.org/ml/gdb/2008-02/msg00064.html

Однако я этим не пользуюсь, поэтому YMMV


1
Спасибо за ссылку; единственное, что макросы зависят от версии библиотеки stl, чего я бы предпочел избежать. +1
Паоло Тедеско

Также немного расстраивает то, что команды вроде "plist foo std :: string" дают синтаксические ошибки. Похоже, что value_type не может содержать знаков препинания.
Bklyn, 09

2
Я не пробовал, но если это работает так же, как и остальная часть GDB, следует заключить имя с пунктированным именем в одинарные кавычки.
jpalecek 09

2
Примечание. Функциональность std :: map в этих сценариях предполагает 32-разрядные типы указателей. На 64-битных машинах замените "+ 4" на "+ 8" везде в файле.
Кайл Симек

pvector не определен в моем gdb (версия 7.5.91.20130417-cvs-ubuntu).
Джефф

92

Существующие ответы на этот вопрос очень устарели. В недавних GCC и GDB это Just Works TM благодаря встроенной поддержке Python в GDB 7.x и принтерам libstdc ++ pretty, которые поставляются с GCC.

Для примера OP я получаю:

(gdb) print m
$1 = std::map with 2 elements = {[1] = 2, [2] = 4}

Если это не сработает автоматически, вы увидите первый пункт списка поддержки STL странице вики GDB.

Вы также можете написать симпатичные принтеры Python для ваших собственных типов, см. Pretty Printing в руководстве GDB.


2
Да, но другие вопросы закрываются как дубликаты, поэтому я хотел, чтобы была свежая информация.
Джонатан Уэйкли

1
Я использую GDB 7.2, и все вышеперечисленное работает ... если у вас небольшая коллекция. Я до сих пор не нашел способа распечатать, скажем, элемент 1543 из вектора 4K, кроме как использовать внутренние структуры реализации STL.
павон

5
Да, в GDB 7.2 и компиляторе icpc я получаю ошибку Could not find operator[].
павон

11
К сожалению, он не работает во всех дистрибутивах. Он не устанавливается по умолчанию в Ubuntu 13.10, и при попытке установить его вручную
nietaki

1
@razeh, Fedora, RHEL (и клоны RHEL). Выполняется исправление, чтобы принтеры также работали в дистрибутивах, где GDB связан с Python 3
Джонатан Уэйкли,

25

Всегда есть очевидное: определите свою собственную тестовую функцию ... Вызовите ее из gdb. Например:

#define SHOW(X) cout << # X " = " << (X) << endl

void testPrint( map<int,int> & m, int i )
{
  SHOW( m[i] );
  SHOW( m.find(i)->first );
}

int
main()
{
    std::map<int,int> m;
    m[1] = 2;
    m[2] = 4;
    return 0;  // Line 15.
}

А также:

....
Breakpoint 1 at 0x400e08: file foo.C, line 15.
(gdb) run
Starting program: /tmp/z/qD 

Breakpoint 1, main () at qD.C:15
(gdb) call testPrint( m, 2)
m[i] = 4
(*m.find(i)).first = 2
(gdb) 

16
пока идет процесс. не так полезно для дампов ядра.
Шон Райли

2
Это полезный совет отладки GDB в целом, а не только с помощью STL. Я храню целую библиотеку вспомогательных функций gdb для большого количества трудно извлекаемых данных, например write_cuda_array_as_image (). Обратите внимание, что некоторые компиляторы удаляют все функции, которые не вызываются, поэтому я помещаю вызов каждой вспомогательной функции после моей main "return 0;". Кроме того, объявление их с помощью extern "C" упрощает их вызов из gdb.
Кайл Симек

21

stl-views.gdbРаньше лучший ответ там был, но не больше.

Это еще не интегрировано в основную веткуGDB , но вот что вы получите, используя ветку archer-tromey-python :

(gdb) list
1   #include <map>
2   int main(){
3       std::map<int,int> m;
4       m[1] = 2;
5       m[2] = 4;
6       return 0;
7   }
(gdb) break 6
Breakpoint 1 at 0x8048274: file map.cc, line 6.
(gdb) run

Breakpoint 1, main () at map.cc:6
6       return 0;
(gdb) print m
$1 = std::map with 2 elements = {
  [1] = 2,
  [2] = 4
}
(gdb) quit

12

Попробуйте удалить ссылки на контейнеры STL: на этой странице: http://www.yolinux.com/TUTORIALS/GDB-Commands.html


Похоже, это бизнес!
Ричард Корден,

На самом деле это те же макросы, что и в предыдущем ответе :) Боюсь, что нет более простого решения.
Паоло Тедеско,

Что это за команда? Вам удалось запустить нас за пределы сайта с огромным количеством нерелевантной информации. Меня не интересует "Как запустить GDB" и прочее.
jww

1

Ответы выше работают и в порядке. Если вы используете stl-views.gdb, вот правильный способ просмотра карт и элементов внутри него. Пусть ваша карта будет такой: std::map<char, int> myMap;

(gdb) pmap myMap char int

т.е. pmap <variable_name> <left_element_type> <right_element_type>чтобы увидеть элементы на карте.

Надеюсь, это поможет.


0

Вы можете обойти вторую проблему ( Cannot evaluate function -- may be inlined), убедившись, что ваш компилятор использует отладочную информацию DWARF-2 (или 3 или 4) при компиляции вашей программы. DWARF-2 включает в себя встраиваемую информацию, поэтому вы должны иметь возможность использовать любой из описанных вами методов для доступа к элементам вашего std::mapконтейнера.

Для компиляции с использованием отладочной информации DWARF-2 добавьте -gdwarf-2флаг в свою команду компиляции.


1
Гм, знание того, где была встроена функция, не позволяет GDB оценивать вызовы этой функции; GDB действительно нужен доступ к внешней копии функции!
SamB
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.