Sprawdzanie zawartości standardowego kontenera (std :: map) za pomocą gdb


93

Przypuśćmy, że mamy coś takiego:

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

Chciałbym móc sprawdzić zawartość mapy, na której działa program z gdb.
Jeśli spróbuję użyć operatora indeksu dolnego, otrzymam:

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

Użycie metody wyszukiwania nie daje lepszych wyników:

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

Czy istnieje sposób, aby to osiągnąć?


Aby wydrukować wszystkie elementy bez obcinania dużych map: stackoverflow.com/questions/47743215/… Bardziej „Nie można ocenić funkcji może być wbudowane” skoncentrowane: stackoverflow.com/questions/40633787/ ...
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Odpowiedzi:


35

Myślę, że nie ma, przynajmniej nie, jeśli twoje źródło jest zoptymalizowane itp. Jednak jest kilka makr dla gdb, które mogą sprawdzić dla ciebie kontenery STL:

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

Jednak nie używam tego, więc YMMV


1
Dzięki za link; jedyną rzeczą jest to, że makra są zależne od wersji bibliotek stl, czego wolałbym unikać. +1
Paolo Tedesco

Trochę frustrujące jest również to, że polecenia takie jak „plist foo std :: string” powodują błędy składniowe. Wygląda na to, że typ_wartości nie może zawierać żadnych znaków interpunkcyjnych.
Bklyn

2
Nie próbowałem, ale jeśli to działa tak samo jak reszta GDB, umieszczenie nazwy w postaci znaków interpunkcyjnych w pojedynczych cudzysłowach powinno to zrobić.
jpalecek

2
Uwaga: funkcjonalność std :: map w tych skryptach zakłada 32-bitowe typy wskaźników. Na komputerach 64-bitowych zamień „+ 4” na „+ 8” w całym pliku.
Kyle Simek

pvector nie jest zdefiniowany w moim gdb (wersja 7.5.91.20130417-cvs-ubuntu).
Jeff,

92

Istniejące odpowiedzi na to pytanie są bardzo nieaktualne. Dzięki najnowszym GCC i GDB to Just Works TM dzięki wbudowanej obsłudze Pythona w GDB 7.x i ładnym drukarkom libstdc ++, które są dostarczane z GCC.

Na przykład OP otrzymuję:

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

Jeśli to nie zadziała automatycznie, zobacz pierwszy punkt na stronie pomocy STL na wiki GDB.

Możesz napisać ładne drukarki Python dla własnych typów, zobacz Pretty Printing w podręczniku GDB.


2
Tak, ale inne pytania są zamykane jako ich duplikaty, więc chciałem, aby zawierały najnowsze informacje.
Jonathan Wakely

1
Używam GDB 7.2 i powyższe działa ... jeśli masz małą kolekcję. Nadal nie znalazłem sposobu, aby wydrukować powiedzmy element 1543 z wektora 4K, poza uciekaniem się do wykorzystania wewnętrznych struktur implementacji STL.
pavon

5
Tak, w GDB 7.2 i kompilatorze icpc pojawia się błąd Could not find operator[].
pavon

11
Niestety nie działa to tylko we wszystkich dystrybucjach. Nie jest instalowany domyślnie w Ubuntu 13.10 i pojawiają się problemy przy próbie instalacji ręcznie
nietaki

1
@razeh, Fedora, RHEL (i klony RHEL). Trwa naprawa, która sprawi, że drukarki będą działać również w dystrybucjach, w których GDB jest połączony z Pythonem 3
Jonathan Wakely,

25

Zawsze jest coś oczywistego: zdefiniuj własną funkcję testową ... Wywołaj ją z gdb. Na przykład:

#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.
}

I:

....
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
tak długo, jak trwa proces. nie jest tak przydatny przy zrzutach pamięci.
sean riley

2
Jest to przydatna rada dotycząca ogólnego debugowania GDB, a nie tylko STL. Utrzymuję całą bibliotekę funkcji pomocniczych gdb dla wielu trudnych do odzyskania danych, np. Write_cuda_array_as_image (). Zauważ, że niektóre kompilatory usuwają wszystkie funkcje, które nie są wywoływane, więc wywołuję każdą funkcję pomocniczą po wyrażeniu „return 0;” w moim main. Również zadeklarowanie ich za pomocą zewnętrznego "C" ułatwia wywoływanie ich z gdb.
Kyle Simek

21

stl-views.gdbKiedyś najlepszą odpowiedź nie było, ale już nie.

To nie jest jeszcze zintegrowane z główną linią GDB, ale oto, co otrzymujesz, używając gałęzi `` 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


1

Powyższe odpowiedzi działają i są w porządku. Jeśli używasz stl-views.gdb, oto właściwy sposób przeglądania map i elementów w nim zawartych. Niech twoja mapa wygląda następująco: std::map<char, int> myMap;

(gdb) pmap myMap char int

tj. pmap <variable_name> <left_element_type> <right_element_type>zobaczyć elementy na mapie.

Mam nadzieję, że to pomoże.


0

Możesz obejść drugi problem ( Cannot evaluate function -- may be inlined), upewniając się, że Twój kompilator używa informacji debugowania DWARF-2 (lub 3 lub 4) podczas kompilowania programu. DWARF-2 zawiera wbudowane informacje, więc powinieneś być w stanie użyć dowolnej z opisanych metod, aby uzyskać dostęp do elementów std::mapkontenera.

Aby skompilować z informacjami debugowania DWARF-2, dodaj -gdwarf-2flagę do polecenia kompilacji.


1
Um, wiedza, gdzie funkcja została wstawiona, nie umożliwia GDB oceny wywołań tej funkcji; GDB naprawdę potrzebuje dostępu do zewnętrznej kopii tej funkcji!
SamB
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.