Як надрукувати елементи вектора C ++ у GDB?


210

Я хочу вивчити вміст std::vectorGDB, як це зробити? Скажімо, це std::vector<int>заради простоти.


3
Подібне запитання: stackoverflow.com/questions/427589/… (посилання у відповіді дуже цікаве).
Паоло Тедеско

Новий, кращий спосіб зробити це в цьому питанні: stackoverflow.com/questions/2492020 / ...
dshepherd

Відповіді:


79

Щоб переглянути вектор std :: векторний вміст myVector, просто введіть GDB:

(gdb) print myVector

Це дасть вихід, подібний до:

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

Щоб досягти вище, вам потрібно мати gdb 7 (я тестував його на gdb 7.01) та якийсь симпатичний принтер python. Процес їх встановлення описаний на gdb wiki .

Більше того, після встановлення вище це добре працює з графічним інтерфейсом налагодження 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 ++, це усуне мертвий код, і GDB не знайде функцію 'print' (ви отримаєте повідомлення про те, що функція вкладена). Тому компілюйте з -fkeep-inline-функціями


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'}}

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 ще друк * ($ arg0._M_impl._M_start) @ $ arg0.size () кінцевий кінець
користувач1541776

el magnifico! mochas gracias
truthadjustr

0

Трохи запізнюємось на вечірку, тому переважно нагадування мені наступного разу, коли я роблю цей пошук!

Я зміг використовувати:

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

надрукувати 4 елементи (як шістнадцятковий), vecпочинаючи з vec[2].

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.