Bỏ qua điều hướng, tới nội dung chính
Học C
Bài 35.330 phút đọc

Xem dữ liệu: print, x và ptype

Sau bài này bạn sẽ làm được

  • Dùng print với các định dạng /x /d /t /c /s
  • In n phần tử liên tiếp bằng cú pháp @
  • Đọc bộ nhớ thô bằng x với đủ ba phần của đặc tả
  • Dùng ptype và display cho vòng lặp gỡ lỗi nhanh

Ba lệnh làm nên chín mươi phần trăm công việc trong GDB: print để xem giá trị, x để xem byte, ptype để xem kiểu. Bài này chạy hết chúng trên một chương trình thật.

#print và các định dạng

terminal
# Dừng ở dòng 41 của dslk.c, sau khi mọi thứ đã khởi tạo
gdb -q -batch -x g2.gdb ./dslk.exe
Breakpoint 1 at 0x40168f: file dslk.c, line 41.

Thread 1 hit Breakpoint 1, main () at dslk.c:41
41	    printf("tong = %d\n", t);
$1 = {5, 3, 9, 1, 7}
$2 = {5, 3, 9, 1, 7}
$3 = {0x5, 0x3, 0x9, 0x1, 0x7}
$4 = 0x9
$5 = 1001
$6 = 65 'A'
$7 = 32
$8 = 60
$9 = 0x3c
LệnhKết quảGhi chú
print a$1 = {5, 3, 9, 1, 7}Mảng in đầy đủ
print a[0]@5$2 = {5, 3, 9, 1, 7}n phần tử từ một địa chỉ
print/x a$3 = {0x5, 0x3, 0x9, 0x1, 0x7}Hệ mười sáu
print/x a[2]$4 = 0x9Một phần tử, hệ mười sáu
print/t a[2]$5 = 1001Hệ hai
print/c 65$6 = 65 'A'Vừa số vừa ký tự
print sizeof(Nut)$7 = 32Tính được cả sizeof
print t$8 = 60Biến thường
print/x t$9 = 0x3cCùng biến, khác định dạng

#In mảng

(gdb) print a
$1 = {5, 3, 9, 1, 7}          /* mang co kich thuoc biet truoc: in het */

(gdb) print a[0]@5
$2 = {5, 3, 9, 1, 7}          /* cu phap @: in n phan tu tu mot dia chi */

(gdb) print *p@10             /* voi con tro: day la cach DUY NHAT */
(gdb) print *ds@so_phan_tu    /* so luong lay tu mot bien */

/* Cu phap @ la thu quan trong nhat trong muc nay:
   voi "int *p = malloc(n * sizeof *p)", GDB khong biet n,
   nen "print p" chi cho ra dia chi va "print *p" chi cho phan tu dau. */
# Mang lon: gioi han so phan tu in ra
(gdb) show print elements
Limit on string chars or array elements to print is 200.

(gdb) set print elements 0          # khong gioi han
(gdb) set print elements 20         # chi 20 phan tu dau

# In dep hon
(gdb) set print array on            # moi phan tu mot dong
(gdb) set print array-indexes on    # kem chi so

(gdb) print a
$1 = {[0] = 5,
      [1] = 3,
      [2] = 9,
      [3] = 1,
      [4] = 7}

# Gom cac gia tri giong nhau
(gdb) show print repeats
Threshold for repeated print elements is 10.

(gdb) print bo_dem
$2 = '\000' <repeats 1023 times>    # thay vi in 1024 so khong

#ptype và whatis

terminal
gdb -q -batch -x g2.gdb ./dslk.exe
type = struct Nut {
    int ma;
    char ten[16];
    struct Nut *sau;
}
type = struct Nut {
    int ma;
    char ten[16];
    struct Nut *sau;
} *
(gdb) ptype Nut          /* dinh nghia DAY DU cua kieu */
(gdb) ptype dau          /* kieu cua bien, dau * o cuoi cho biet la con tro */
(gdb) whatis dau         /* chi TEN kieu, khong khai trien */
$1 = type = Nut *

(gdb) ptype tong         /* ca chu ky ham */
type = int (const Nut *)

(gdb) ptype/o Nut        /* GDB 8.1 tro len: kem OFFSET va kich thuoc */
# Ba lenh info tra cuu ky hieu

(gdb) info functions tong        # moi ham co ten chua "tong"
All functions matching regular expression "tong":

File dslk.c:
static int tong(const Nut *);

(gdb) info variables              # moi bien toan cuc va tinh
(gdb) info types Nut              # moi kieu khop
(gdb) info line dslk.c:23         # dia chi cua mot dong
(gdb) info symbol 0x4015be        # ky hieu tai mot dia chi
(gdb) info scope tong             # bien nao song trong ham tong

#Lệnh x: đọc bộ nhớ thô

terminal
gdb -q -batch -x g2.gdb ./dslk.exe
0x61fe30:	5	3	9	1
0x61fe40:	7
0x61fe30:	0x05	0x00	0x00	0x00	0x03	0x00	0x00	0x00
0x61fe38:	0x09	0x00	0x00	0x00	0x01	0x00	0x00	0x00
0x61fe40:	0x07	0x00	0x00	0x00
0xb82834:	"ba"
LệnhDùng khi
x/16xb &svXem từng byte của một struct, kể cả phần đệm
x/8xg $spXem tám ô tám byte trên đỉnh ngăn xếp
x/s tenXem một chuỗi, dừng ở ký tự kết thúc
x/3s tenXem ba chuỗi liên tiếp trong bộ đệm
x/10i $pcXem mười lệnh máy sắp chạy
x/4f dXem bốn số thực
x/20xw pXem hai mươi word từ một con trỏ nghi ngờ
x/1000xb bo_demĐổ toàn bộ một bộ đệm ra

#display và info

display x                 # in x sau MOI lan dung
display/x co              # kem dinh dang
display *p                # theo doi thu con tro tro toi
info display              # liet ke
undisplay 1               # bo mot cai
delete display            # bo het

/* display la thu bien viec buoc tung dong thanh de chiu:
   thay vi go "print x" sau moi lenh next, ban dang ky mot lan
   va GDB in tu dong. */
terminal
# display u, rồi next: GDB tự in u sau khi bước
gdb -q -batch -x g7.gdb ./buoc.exe
Thread 1 hit Breakpoint 1, tinh (a=3, b=4) at buoc.c:10
10	    int u = binh_phuong(a);
11	    int v = binh_phuong(b);
1: u = 9
Lệnh infoCho biết
info localsMọi biến cục bộ của khung hiện tại
info argsTham số của hàm hiện tại
info frameChi tiết khung: địa chỉ trả về, con trỏ khung
info registersThanh ghi số nguyên
info all-registersCả thanh ghi SSE và thanh ghi thực
info breakpointsDanh sách điểm dừng và watchpoint
info threadsCác luồng đang chạy
info sharedlibraryThư viện động đã nạp
info proc mappingsBản đồ bộ nhớ, xem trang nào đọc ghi được
info sourceTệp nguồn hiện tại và cờ dịch

#Sửa giá trị khi đang chạy

set var x = 100                 # sua bien
set var p->ma = 5               # sua truong qua con tro
set var a[2] = 42               # sua phan tu mang
set var s[0] = 'A'              # sua ky tu

set var $rax = 0                # sua thanh ghi

call ham(1, 2)                  # goi mot ham
print ham(1, 2)                 # giong call nhung in ket qua

return                          # ep ham hien tai tra ve NGAY
return 0                        # tra ve voi gia tri 0

jump 42                         # nhay toi dong 42, KHONG chay cac dong giua

Tự làm thử

  1. In một mảng bằng cả print a và print a[0]@5, so hai cách.
  2. In cùng một biến ở năm định dạng khác nhau.
  3. Chạy ptype/o trên một struct có đệm và đối chiếu với sizeof.
  4. Dùng x/20xb trên một số nguyên và xác định thứ tự byte của máy bạn.
  5. Dùng biến tiện dụng $p để đi qua ba nút của một danh sách liên kết.
  6. Đặt điểm dừng sau malloc, dùng set var p = 0 để đi vào nhánh xử lý hết bộ nhớ.

Trình chấm điểm tự động sẽ được bổ sung ở giai đoạn sau. Hiện tại bạn tự chạy thử trên máy.

Tóm tắt

  • Cú pháp @ là cách duy nhất in được n phần tử từ một con trỏ, vì GDB không biết kích thước vùng cấp phát.
  • ptype/o hiện cả độ dời, kích thước và phần đệm, trả lời ngay câu hỏi vì sao struct to hơn tổng các trường.
  • Đặc tả của x có ba phần: số lượng, định dạng, kích thước đơn vị. Gõ x trống thì lặp lại đặc tả cũ.
  • print đánh giá biểu thức C đầy đủ, gọi được cả hàm trong chương trình, nhưng lời gọi đó chạy thật và có tác dụng phụ thật.
  • Luôn viết set var x = ... chứ không phải set x = ..., vì nhiều tên biến trùng với tên lệnh của GDB.