Как мне распечатать элементы вектора C ++ в GDB?

210

Я хочу проверить содержимое a std::vectorв GDB, как мне это сделать? Допустим, это std::vector<int>ради простоты.

Джон Картер
источник
3
Аналогичный вопрос: stackoverflow.com/questions/427589/… (ссылка в ответе очень интересна).
Паоло Тедеско
Новый, лучший способ сделать это в этом вопросе: stackoverflow.com/questions/2492020/…
dshepherd

Ответы:

79

Чтобы просмотреть содержимое вектора std :: vector myVector, просто введите GDB:

(gdb) print myVector

Это даст результат, похожий на:

$1 = std::vector of length 3, capacity 4 = {10, 20, 30}

Чтобы достичь выше, вам нужно иметь gdb 7 (я тестировал его на gdb 7.01) и немного python pretty-printer. Процесс их установки описан на вики-сайте gdb .

Более того, после установки выше, это хорошо работает с графическим интерфейсом отладчика Eclipse C ++ (и любой другой IDE, использующей GDB, как мне кажется).

Михал Онищук
источник
16
Это прекрасно работает, если элементы вектора напрямую интерпретируются. Но это не поможет, если вектор содержит указатели на интересующие элементы.
Wallyk
Честно говоря, я не считаю вики- страницу GDB особенно читабельной, может быть, потому что она «слегка» устарела сейчас? Например, у меня сложилось впечатление, что предлагаемое содержание $HOME/.gdbinitбыло необходимо. На данный момент у меня нет такого файла и я gdbправильно показываю содержимое std::vector. Однако, поскольку во время моих «бессвязных» попыток я только что установил, а затем не установил cgdb, и я уже libstdc++5установил, я понятия не имею, почему красивая печать не работает, пока она работает.
Энрико Мария Де Анжелис
257

С GCC 4.1.2, чтобы напечатать весь std :: vector <int> с именем myVector, сделайте следующее:

print *(myVector._M_impl._M_start)@myVector.size()

Чтобы напечатать только первые N элементов, выполните:

print *(myVector._M_impl._M_start)@N

объяснение

Вероятно, это сильно зависит от версии вашего компилятора, но для GCC 4.1.2 указатель на внутренний массив:

myVector._M_impl._M_start 

И команда GDB для печати N элементов массива, начиная с указателя P:

print P@N

Или в краткой форме (для стандартного .gdbinit):

p P@N
Джон Картер
источник
4
Хе-хе, это то, что беспокоило меня раньше, так что я просто посмотрел это сегодня утром и добавил это как памятку для себя (как рекомендовал сам Джефф).
Джон Картер
3
Также, если вам нужен только конкретный векторный элемент, myVector._M_impl._M_start + n (для n-го элемента)
моряк
1
Не работает для меня Cannot evaluate function -- may be inlined
Wallyk
1
Чтобы напечатать один элемент, например, 2-й элемент: print (myVector._M_impl._M_start) [2]
jfritz42
2
Чтобы найти специальные имена (и _M_implт. Д.) Для вашего компилятора в GDB 7.0+, используйтеprint /r myVector
Eponymous
14

«Наблюдение» за STL-контейнерами во время отладки представляет собой некоторую проблему. Вот 3 разных решения, которые я использовал в прошлом, но ни одно из них не является идеальным.

1) Используйте сценарии GDB с http://clith.com/gdb_stl_utils/. Эти сценарии позволяют распечатывать содержимое практически всех контейнеров STL. Проблема в том, что это не работает для вложенных контейнеров, таких как стек наборов.

2) Visual Studio 2005 имеет фантастическую поддержку для просмотра контейнеров STL. Это работает для вложенных контейнеров, но для их реализации только для STL и не работает, если вы помещаете контейнер STL в контейнер Boost.

3) Напишите свою собственную функцию (или метод) печати для определенного элемента, который вы хотите распечатать во время отладки, и используйте «вызов» в GDB для печати элемента. Обратите внимание, что если ваша функция печати нигде в коде не вызывается, g ++ выполнит удаление мертвого кода и функция 'print' не будет найдена GDB (вы получите сообщение о том, что функция встроена). Так что скомпилируйте с -fkeep-inline-functions

Нихилу
источник
11

поместите следующее в ~ / .gdbinit

define print_vector
    if $argc == 2
        set $elem = $arg0.size()
        if $arg1 >= $arg0.size()
            printf "Error, %s.size() = %d, printing last element:\n", "$arg0", $arg0.size()
            set $elem = $arg1 -1
        end
        print *($arg0._M_impl._M_start + $elem)@1
    else
        print *($arg0._M_impl._M_start)@$arg0.size()
    end
end

document print_vector
Display vector contents
Usage: print_vector VECTOR_NAME INDEX
VECTOR_NAME is the name of the vector
INDEX is an optional argument specifying the element to display
end

После перезапуска GDB (или поиска ~ / .gdbinit) покажите соответствующую справку, подобную этой

gdb) help print_vector
Display vector contents
Usage: print_vector VECTOR_NAME INDEX
VECTOR_NAME is the name of the vector
INDEX is an optional argument specifying the element to display

Пример использования:

(gdb) print_vector videoconfig_.entries 0
$32 = {{subChannelId = 177 '\261', sourceId = 0 '\000', hasH264PayloadInfo = false, bitrate = 0,     payloadType = 68 'D', maxFs = 0, maxMbps = 0, maxFps = 134, encoder = 0 '\000', temporalLayers = 0 '\000'}}
badeip
источник
2
спасибо за код! Я предполагаю, что есть опечатка и "print * ($ arg0._M_impl._M_start + $ elem) @ 1" должно быть "print * ($ arg0._M_impl._M_start + $ arg1) @ 1"? Я использую следующую модификацию: определить print_vector, если $ argc == 2, если $ arg1> = $ arg0.size () - 1 printf "Ошибка,% s.size () =% d, печать последнего элемента: \ n", " $ arg0 ", $ arg0.size () - 1 конец печати * ($ arg0._M_impl._M_start + $ arg1) @ 1 else print * ($ arg0._M_impl._M_start) @ $ arg0.size () end end
user1541776
El Magnifico! mochas gracias
trueadjustr
0

Немного опоздал на вечеринку, поэтому в основном напомню мне в следующий раз, когда я сделаю этот поиск!

Я был в состоянии использовать:

p/x *(&vec[2])@4

напечатать 4 элемента (в шестнадцатеричном виде), vecначиная с vec[2].

Майк П
источник