Kiểm tra nội dung vùng chứa tiêu chuẩn (std :: map) với gdb


93

Giả sử có một cái gì đó như thế này:

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

Tôi muốn có thể kiểm tra nội dung của bản đồ đang chạy chương trình từ gdb.
Nếu tôi thử sử dụng toán tử chỉ số, tôi nhận được:

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

Sử dụng phương pháp tìm không mang lại kết quả tốt hơn:

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

Có cách nào để hoàn thành nó không?

Câu trả lời:


35

Tôi nghĩ rằng không có, ít nhất là không nếu nguồn của bạn được tối ưu hóa, v.v. Tuy nhiên, có một số macro cho gdb có thể kiểm tra vùng chứa STL cho bạn:

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

Tuy nhiên, tôi không sử dụng cái này, vì vậy YMMV


1
Cảm ơn các liên kết; điều duy nhất là macro phụ thuộc vào phiên bản thư viện stl, điều mà tôi muốn tránh. +1
Paolo Tedesco

Cũng hơi bực bội khi các lệnh như "plist foo std :: string" gây ra lỗi cú pháp. Có vẻ như value_type không thể chứa bất kỳ dấu câu nào.
Bklyn

2
Tôi chưa thử, nhưng nếu cách này hoạt động giống như phần còn lại của GDB, thì nên đặt tên bằng dấu chấm câu trong dấu ngoặc kép.
jpalecek

2
Lưu ý: chức năng bản đồ std :: trong các tập lệnh này giả định các loại con trỏ 32 bit. Đối với máy 64-bit, hãy thay thế "+ 4" thành "+ 8" ở mọi nơi trong tệp.
Kyle Simek

pvector không được định nghĩa trong gdb của tôi (phiên bản 7.5.91.20130417-cvs-ubuntu).
Jeff

91

Các câu trả lời hiện có cho câu hỏi này rất lỗi thời. Với GCC và GDB gần đây, nó chỉ hoạt động TM nhờ hỗ trợ Python tích hợp trong GDB 7.x và các máy in libstdc ++ đẹp đi kèm với GCC.

Đối với ví dụ của OP, tôi nhận được:

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

Nếu nó không tự động hoạt động, bạn hãy xem dấu đầu dòng đầu tiên trên trang Hỗ trợ STL của wiki GDB.

Bạn cũng có thể viết các máy in đẹp bằng Python cho các loại của riêng mình, hãy xem In ấn đẹp trong hướng dẫn sử dụng GDB.


2
Có, nhưng các câu hỏi khác đang được đóng lại vì trùng lặp với nó, vì vậy tôi muốn nó có thông tin gần đây.
Jonathan Wakely

1
Tôi đang sử dụng GDB 7.2 và các hoạt động ở trên ... nếu bạn có một bộ sưu tập nhỏ. Tôi vẫn chưa tìm thấy bất kỳ cách nào để in phần tử nói 1543 từ một vectơ 4K, ngoài việc sử dụng các cấu trúc bên trong của việc triển khai STL.
pavon

5
Có, trong GDB 7.2 và trình biên dịch icpc, tôi gặp lỗi Could not find operator[].
pavon

11
Thật không may, nó không "Chỉ hoạt động" trong tất cả các bản phân phối. Nó không được cài đặt theo mặc định trong Ubuntu 13.10 và có vấn đề khi bạn cố gắng để cài đặt nó bằng tay
nietaki

1
@razeh, Fedora, RHEL (và RHEL sao chép). Có cách khắc phục cơ bản dở dang để làm cho máy in cũng làm việc trên distro nơi GDB được liên kết với Python 3
Jonathan Wakely

25

Luôn luôn có một điều hiển nhiên: Xác định chức năng kiểm tra của riêng bạn ... Gọi nó từ gdb. Ví dụ:

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

Và:

....
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
miễn là quá trình đang chạy. không hữu ích cho các bãi chứa lõi.
sean riley 14/08/09

2
Đây là lời khuyên hữu ích để gỡ lỗi GDB nói chung, không chỉ với STL. Tôi lưu giữ toàn bộ thư viện các hàm trợ giúp gdb cho rất nhiều dữ liệu khó truy xuất, ví dụ: write_cuda_array_as_image (). Lưu ý rằng một số trình biên dịch sẽ loại bỏ bất kỳ hàm nào không được gọi, vì vậy tôi thực hiện lệnh gọi đến từng hàm trợ giúp sau "return 0;" của main. Việc khai báo chúng bằng extern "C" giúp việc gọi chúng từ gdb dễ dàng hơn.
Kyle Simek

21

Các stl-views.gdbtừng là câu trả lời tốt nhất là có, nhưng không được nữa.

Đây không phải là tích hợp vào Mainline GDB, nhưng đây là những gì bạn nhận được bằng cách sử dụng 'Archer-tromey-python' chi nhánh :

(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

Thử hủy tham chiếu STL Container: trên trang này: http://www.yolinux.com/TUTORIALS/GDB-Commands.html


Đây có vẻ là doanh nghiệp!
Richard Corden

Chúng thực sự là các macro giống như trong câu trả lời trước :) Tôi e rằng không có giải pháp nào đơn giản hơn.
Paolo Tedesco

Lệnh là gì? Bạn đã quản lý để điều hành chúng tôi bên ngoài với vô số thông tin không liên quan. Tôi không quan tâm đến "Cách bắt đầu GDB" và những thứ khác.
jww

1

Các câu trả lời trên đang hoạt động và tốt. Trong trường hợp bạn đang sử dụng stl-views.gdb, đây là cách thích hợp để xem bản đồ và các yếu tố bên trong nó. Hãy để bản đồ của bạn như sau: std::map<char, int> myMap;

(gdb) pmap myMap char int

tức là pmap <variable_name> <left_element_type> <right_element_type>để xem các yếu tố trong bản đồ.

Hy vọng rằng sẽ giúp.


0

Bạn có thể giải quyết vấn đề thứ hai ( Cannot evaluate function -- may be inlined) bằng cách đảm bảo rằng trình biên dịch của bạn sử dụng thông tin gỡ lỗi DWARF-2 (hoặc 3 hoặc 4) khi bạn biên dịch chương trình của mình. DWARF-2 bao gồm thông tin nội tuyến, vì vậy bạn có thể sử dụng một trong các phương pháp mà bạn đã mô tả để truy cập các phần tử củastd::map chứa .

Để biên dịch với thông tin gỡ lỗi DWARF-2, hãy thêm -gdwarf-2cờ vào lệnh biên dịch của bạn.


1
Ừm, việc biết vị trí của một hàm đã được nội tuyến không giúp GDB có thể đánh giá các lệnh gọi đến hàm đó; GDB thực sự cần quyền truy cập vào một bản sao ngoại tuyến của hàm!
SamB
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.