Перевірка вмісту стандартного контейнера (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

Чи є спосіб досягти цього?

Відповіді:


35

Я думаю, що цього немає, принаймні ні, якщо ваше джерело оптимізовано і т. Д. Однак є деякі макроси для gdb, які можуть перевірити для вас контейнери STL:

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

Однак я цим не користуюся, тому YMMV


1
Дякую за посилання; єдине, що макроси залежать від версії бібліотек stl, чого я волів би уникати. +1
Паоло Тедеско

Це також трохи засмучує, що команди на зразок "plist foo std :: string" дають синтаксичні помилки. Здається, тип_значення не може містити знаків пунктуації.
Bklyn

2
Я не пробував, але якщо це працює так само, як і решта GDB, слід вкласти ім'я з розділовими назвами в одинарні лапки.
jpalecek

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

pvector не визначений у моєму gdb (версія 7.5.91.20130417-cvs-ubuntu).
Джефф

91

Існуючі відповіді на це питання дуже застарілі. З нещодавніми GCC та GDB це просто працює TM завдяки вбудованій підтримці Python у GDB 7.x та симпатичних принтерах libstdc ++, що постачаються з GCC.

Для прикладу OP я отримую:

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

Якщо це не працює автоматично, ви бачите перший пункт на сторінці підтримки STL у вікі GDB.

Ви також можете писати симпатичні принтери для Python для власних типів, див. « Гарненький друк» у посібнику GDB.


2
Так, але інші питання закриваються як їх дублікати, тому я хотів, щоб у них була свіжа інформація.
Джонатан Уейклі

1
Я використовую GDB 7.2 і вищезазначені роботи ... якщо у вас невелика колекція. Я все ще не знайшов способу надрукувати елемент сказання 1543 з вектора 4K, крім вдавання до використання внутрішніх структур реалізації STL.
Павон

5
Так, у GDB 7.2 та компіляторі icpc я отримую помилку Could not find operator[].
pavon

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 (). Зверніть увагу, що деякі компілятори видаляють будь-які функції, які не викликаються, тому я здійснюю виклик кожної допоміжної функції після мого основного "return 0;". Також оголошення їх зовнішнім знаком "C" полегшує виклик з gdb.
Кайл Сімек

21

stl-views.gdbРаніше краща відповідь там був, але не більше.

Це не інтегрована в основну гілку GDBще, але ось те , що ви отримаєте з допомогою «Арчер-tromey-пітон» філія :

(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.