Memeriksa konten kontainer standar (std :: map) dengan gdb

93

Misalkan memiliki sesuatu seperti ini:

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

Saya ingin dapat memeriksa isi peta yang menjalankan program dari gdb.
Jika saya mencoba menggunakan operator subskrip, saya mendapatkan:

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

Menggunakan metode find tidak memberikan hasil yang lebih baik:

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

Apakah ada cara untuk menyelesaikan ini?

Paolo Tedesco
sumber
Untuk mencetak semua elemen tanpa memotong peta besar: stackoverflow.com/questions/47743215/… Lebih banyak "Tidak dapat mengevaluasi fungsi mungkin sebaris" difokuskan: stackoverflow.com/questions/40633787/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Jawaban:

35

Saya pikir tidak ada, setidaknya tidak jika sumber Anda dioptimalkan dll. Namun, ada beberapa makro untuk gdb yang dapat memeriksa kontainer STL untuk Anda:

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

Namun, saya tidak menggunakan ini, jadi YMMV

jpalecek.dll
sumber
1
Terima kasih untuk tautannya; satu-satunya hal adalah bahwa makro bergantung dari versi pustaka stl, yang lebih suka saya hindari. +1
Paolo Tedesco
Ini juga agak membuat frustasi bahwa perintah seperti "plist foo std :: string" memberikan kesalahan sintaks. Tampaknya value_type tidak boleh berisi tanda baca apa pun.
Bklyn
2
Saya belum mencoba, tetapi jika ini berfungsi sama dengan GDB lainnya, melampirkan nama dengan nama bersela dalam tanda kutip tunggal harus melakukannya.
jpalecek
2
Catatan: fungsionalitas std :: map dalam skrip ini mengasumsikan tipe penunjuk 32-bit. Untuk mesin 64-bit, ganti "+ 4" menjadi "+ 8" di mana pun dalam file.
Kyle Simek
pvector tidak ditentukan di gdb saya (versi 7.5.91.20130417-cvs-ubuntu).
Jeff
92

Jawaban yang ada untuk pertanyaan ini sudah sangat kuno. Dengan GCC dan GDB baru-baru ini, ini Just Works TM berkat dukungan Python bawaan di GDB 7.x dan printer cantik libstdc ++ yang disertakan dengan GCC.

Untuk contoh OP saya dapatkan:

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

Jika tidak bekerja secara otomatis untuk Anda, lihat poin peluru pertama di halaman Dukungan STL di wiki GDB.

Anda juga dapat menulis printer cantik Python untuk tipe Anda sendiri, lihat Pretty Printing di manual GDB.

Jonathan Wakely
sumber
2
Ya, tetapi pertanyaan lain ditutup sebagai duplikat, jadi saya ingin memiliki informasi terbaru.
Jonathan Wakely
1
Saya menggunakan GDB 7.2 dan yang di atas berfungsi ... jika Anda memiliki koleksi kecil. Saya masih belum menemukan cara untuk mencetak say elemen 1543 dari vektor 4K, selain menggunakan struktur internal implementasi STL.
pavon
5
Ya, di GDB 7.2 dan compiler icpc saya mendapatkan error Could not find operator[].
pavon tanggal
11
Sayangnya itu tidak "Hanya Bekerja" di semua distro. Itu tidak diinstal secara default di Ubuntu 13.10 dan ada masalah ketika Anda mencoba menginstalnya secara manual
nietaki
1
@razeh, Fedora, RHEL (dan klon RHEL). Ada perbaikan yang sedang berlangsung untuk membuat printer juga berfungsi pada distro di mana GDB ditautkan ke Python 3
Jonathan Wakely
25

Selalu ada yang jelas: Tentukan fungsi pengujian Anda sendiri ... Sebut saja dari gdb. Misalnya:

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

Dan:

....
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) 
Tuan Ree
sumber
16
selama prosesnya berjalan. tidak begitu berguna untuk core-dumps.
sean riley
2
Ini adalah saran berguna untuk men-debug GDB secara umum, tidak hanya dengan STL. Saya menyimpan seluruh pustaka fungsi pembantu gdb untuk banyak data yang sulit diambil, misalnya write_cuda_array_as_image (). Perhatikan bahwa beberapa kompiler akan menghapus semua fungsi yang tidak dipanggil, jadi saya menempatkan panggilan ke setiap fungsi pembantu setelah "return 0;" utama saya. Juga mendeklarasikannya dengan "C" eksternal membuat panggilan dari gdb lebih mudah.
Kyle Simek
21

The stl-views.gdbdigunakan untuk menjadi jawaban terbaik ada, tapi sekarang tidak lagi.

Hal ini tidak terintegrasi ke dalam arus utama GDB, tapi di sini adalah apa yang Anda mendapatkan menggunakan 'pemanah-tromey-python' cabang :

(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
Bekerja di Rusia
sumber
12

Coba De-Referencing STL Containers: di halaman ini: http://www.yolinux.com/TUTORIALS/GDB-Commands.html

anand
sumber
Ini terlihat seperti bisnis!
Richard Corden
Mereka sebenarnya adalah makro yang sama seperti pada jawaban sebelumnya :) Saya khawatir tidak ada solusi yang lebih sederhana.
Paolo Tedesco
Apa perintahnya? Anda berhasil membuat kami keluar dari situs dengan banyak sekali informasi yang tidak relevan. Saya tidak tertarik dengan "Bagaimana cara memulai GDB" dan yang lainnya.
jww
1

Jawaban di atas berfungsi dan baik-baik saja. Jika Anda menggunakan stl-views.gdb, berikut adalah cara yang tepat untuk menampilkan peta dan elemen di dalamnya. Biarkan peta Anda sebagai berikut: std::map<char, int> myMap;

(gdb) pmap myMap char int

yaitu pmap <variable_name> <left_element_type> <right_element_type>untuk melihat elemen di peta.

Semoga membantu.

Mazhar MIK
sumber
0

Anda bisa mengatasi masalah kedua ( Cannot evaluate function -- may be inlined) dengan memastikan bahwa kompilator Anda menggunakan informasi debug DWARF-2 (atau 3 atau 4) saat Anda mengompilasi program Anda. DWARF-2 menyertakan informasi sebaris, jadi Anda harus dapat menggunakan salah satu metode yang Anda jelaskan untuk mengakses elemen std::mappenampung Anda .

Untuk mengompilasi dengan info debug DWARF-2, tambahkan -gdwarf-2tanda ke perintah kompilasi Anda.

Dan
sumber
1
Um, mengetahui di mana suatu fungsi telah sebaris tidak memungkinkan GDB mengevaluasi panggilan ke fungsi itu; GDB benar-benar membutuhkan akses ke salinan fungsi yang out-of-line!
SamB