การตรวจสอบเนื้อหาคอนเทนเนอร์มาตรฐาน (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

มีวิธีที่จะทำให้สำเร็จหรือไม่?


หากต้องการพิมพ์องค์ประกอบทั้งหมดโดยไม่ต้องตัดทอนแผนที่ขนาดใหญ่: stackoverflow.com/questions/47743215/… "ไม่สามารถประเมินฟังก์ชันอาจจะ
อินไลน์

คำตอบ:


35

ฉันคิดว่าไม่มีอย่างน้อยถ้าแหล่งที่มาของคุณได้รับการปรับให้เหมาะสมเป็นต้นอย่างไรก็ตามมีมาโครบางตัวสำหรับ gdb ที่สามารถตรวจสอบคอนเทนเนอร์ STL ให้คุณได้:

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

อย่างไรก็ตามฉันไม่ได้ใช้สิ่งนี้ดังนั้น YMMV


1
ขอบคุณสำหรับลิงค์; สิ่งเดียวคือมาโครขึ้นอยู่กับเวอร์ชันไลบรารี stl ซึ่งฉันต้องการหลีกเลี่ยง +1
Paolo Tedesco

นอกจากนี้ยังน่าหงุดหงิดเล็กน้อยที่คำสั่งเช่น "plist foo std :: string" ให้ข้อผิดพลาดทางไวยากรณ์ ดูเหมือนว่า value_type ต้องไม่มีเครื่องหมายวรรคตอน
Bklyn

2
ฉันยังไม่ได้ลอง แต่ถ้ามันใช้งานได้เหมือนกับ GDB ที่เหลือการใส่ชื่อที่มีเครื่องหมายวรรคตอนในเครื่องหมายคำพูดเดี่ยวก็ควรทำ
jpalecek

2
หมายเหตุ: ฟังก์ชัน std :: map ในสคริปต์เหล่านี้ถือว่าเป็นประเภทตัวชี้ 32 บิต สำหรับเครื่อง 64 บิตให้แทนที่ "+ 4" เป็น "+ 8" ทุกที่ในไฟล์
Kyle Simek

pvector ไม่ได้กำหนดไว้ใน gdb ของฉัน (เวอร์ชัน 7.5.91.20130417-cvs-ubuntu)
Jeff

92

คำตอบมีอยู่คำถามนี้เป็นอย่างมากจากวันที่ ด้วย GCC และ GDB ล่าสุดมัน Just Works TMด้วยการรองรับ Python ในตัวใน GDB 7.x และเครื่องพิมพ์สวย libstdc ++ ที่มาพร้อมกับ GCC

สำหรับตัวอย่างของ OP ฉันได้รับ:

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

หากไม่ทำงานโดยอัตโนมัติให้คุณเห็นสัญลักษณ์แสดงหัวข้อย่อยแรกในหน้าการสนับสนุน STLของวิกิ GDB

คุณสามารถเขียนเครื่องพิมพ์ Python สำหรับประเภทของคุณเองได้เช่นกันดูPretty Printingในคู่มือ GDB


2
ใช่ แต่คำถามอื่น ๆ กำลังถูกปิดเนื่องจากคำถามซ้ำกันดังนั้นฉันจึงต้องการให้มีข้อมูลล่าสุด
Jonathan Wakely

1
ฉันใช้ GDB 7.2 และข้างต้นใช้งานได้ ... ถ้าคุณมีคอลเล็กชันขนาดเล็ก ฉันยังไม่พบวิธีใดในการพิมพ์องค์ประกอบที่ 1543 จากเวกเตอร์ 4K นอกเหนือจากการใช้โครงสร้างภายในของการใช้งาน STL
pavon

5
ใช่ใน GDB 7.2 และเรียบเรียง ICPC Could not find operator[]ที่ฉันได้รับข้อผิดพลาด
pavon

11
น่าเสียดายที่มันไม่ได้ "Just Work" ในทุกพื้นที่ ไม่ได้ติดตั้งโดยค่าเริ่มต้นใน Ubuntu 13.10 และมีปัญหาเมื่อคุณพยายามติดตั้งด้วยตนเอง
nietaki

1
@razeh, Fedora, RHEL (และโคลน RHEL) กำลังดำเนินการแก้ไขเพื่อให้เครื่องพิมพ์ทำงานบน distros ที่ GDB เชื่อมโยงกับ Python 3
Jonathan Wakely

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
ตราบเท่าที่กระบวนการทำงานอยู่ ไม่ค่อยมีประโยชน์สำหรับการทิ้งหลัก
sean riley

2
นี่เป็นคำแนะนำที่เป็นประโยชน์ในการดีบัก GDB โดยทั่วไปไม่ใช่เฉพาะกับ STL ฉันเก็บไลบรารีทั้งหมดของฟังก์ชันตัวช่วย gdb สำหรับข้อมูลที่ดึงยากมากมายเช่น write_cuda_array_as_image () โปรดทราบว่าคอมไพเลอร์บางตัวจะตัดฟังก์ชันที่ไม่ได้ถูกเรียกออกไปดังนั้นฉันจึงโทรไปยังฟังก์ชันตัวช่วยแต่ละตัวหลังจาก "return 0;" ของ main ของฉัน นอกจากนี้การประกาศด้วย "C" ภายนอกทำให้เรียกใช้จาก gdb ได้ง่ายขึ้น
Kyle Simek

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


สิ่งเหล่านี้ดูเหมือนจะเป็นธุรกิจ!
Richard Corden

จริงๆแล้วมันเป็นมาโครเดียวกับคำตอบก่อนหน้านี้ :) ฉันเกรงว่าจะไม่มีวิธีแก้ปัญหาที่ง่ายกว่านี้
Paolo Tedesco

คำสั่งคืออะไร? คุณจัดการเพื่อเรียกใช้เรานอกสถานที่พร้อมข้อมูลที่ไม่เกี่ยวข้องจำนวนมาก ฉันไม่สนใจ "วิธีเริ่ม 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 debug info ให้เพิ่ม-gdwarf-2แฟล็กในคำสั่งคอมไพล์ของคุณ


1
อืมการรู้ว่าฟังก์ชันถูกอินไลน์ไว้ที่ใดไม่ทำให้ GDB ประเมินการเรียกไปยังฟังก์ชันนั้นได้ GDB ต้องการการเข้าถึงสำเนาของฟังก์ชันที่ไม่อยู่ในบรรทัดจริงๆ!
SamB
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.