GDB調試指南-變量查看

前言

在啓動調試以及設置斷點以後,就到了咱們很是關鍵的一步-查看變量。GDB調試最大的目的之一就是走查代碼,查看運行結果是否符合預期。既然如此,咱們就不得不瞭解一些查看各類類型變量的方法,以幫助咱們進一步定位問題。php

準備工做

在查看變量以前,須要先啓動調試並設置斷點,該部份內容可參考《GDB調試指南-啓動調試》和《GDB調試指南-斷點設置》。後面的內容都基於在某個位置已經斷住。css

本文輔助說明程序以下:
testGdb.chtml

//testGdb.c
#include<stdio.h>
#include<stdlib.h>
#include"testGdb.h"
int main(void)
{
    int a = 10; //整型
    int b[] = {1,2,3,5};  //數組
    char c[] = "hello,shouwang";//字符數組
    /*申請內存,失敗時退出*/    
    int *d = (int*)malloc(a*sizeof(int));
    if(NULL == d)
    {
        printf("malloc error\n");
        return -1;
    }
    /*賦值*/
    for(int i=0; i < 10;i++)
    {
        d[i] = i;
    }
    free(d);
    d = NULL;
    float e = 8.5f;
    return 0;
}

testGdb.h算法

int a = 11;

編譯:sql

$ gcc -g -o testGdb testGdb.o

變量查看

打印基本類型變量,數組,字符數組

最多見的使用即是使用print(可簡寫爲p)打印變量內容。
例如,打印基本類型,數組,字符數組等直接使用p 變量名便可:數據庫

(gdb) p a
$1 = 10
(gdb) p b
$2 = {1, 2, 3, 5}
(gdb) p c
$3 = "hello,shouwang"
(gdb) 

固然有時候,多個函數或者多個文件會有同一個變量名,這個時候能夠在前面加上文件名或者函數名來區分:express

(gdb) p 'testGdb.h'::a
$1 = 11
(gdb) p 'main'::b
$2 = {1, 2, 3, 5}
(gdb) 

這裏所打印的a值是咱們定義在testGdb.h文件裏的,而b值是main函數中的b。編程

打印指針指向內容

若是仍是使用上面的方式打印指針指向的內容,那麼打印出來的只是指針地址而已,例如:數組

(gdb) p d
$1 = (int *) 0x602010
(gdb) 

而若是想要打印指針指向的內容,須要解引用:ruby

(gdb) p *d
$2 = 0
(gdb) p *d@10
$3 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
(gdb) 

從上面能夠看到,僅僅使用*只能打印第一個值,若是要打印多個值,後面跟上@並加上要打印的長度。
或者@後面跟上變量值:

(gdb) p *d@a
$2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
(gdb) 

因爲a的值爲10,而且是做爲整型指針數據長度,所以後面能夠直接跟着a,也能夠打印出全部內容。

另外值得一提的是,$可表示上一個變量,而假設此時有一個鏈表linkNode,它有next成員表明下一個節點,則可以使用下面方式不斷打印鏈表內容:

(gdb) p *linkNode
(這裏顯示linkNode節點內容)
(gdb) p *$.next
(這裏顯示linkNode節點下一個節點的內容)

若是想要查看前面數組的內容,你能夠將下標一個一個累加,還能夠定義一個相似UNIX環境變量,例如:

(gdb) set $index=0
(gdb) p b[$index++]
$11 = 1
(gdb) p b[$index++]
$12 = 2
(gdb) p b[$index++]
$13 = 3

這樣就不須要每次修改下標去打印啦。

按照特定格式打印變量

對於簡單的數據,print默認的打印方式已經足夠了,它會根據變量類型的格式打印出來,可是有時候這還不夠,咱們須要更多的格式控制。常見格式控制字符以下:

  • x 按十六進制格式顯示變量。
  • d 按十進制格式顯示變量。
  • u 按十六進制格式顯示無符號整型。
  • o 按八進制格式顯示變量。
  • t 按二進制格式顯示變量。
  • a 按十六進制格式顯示變量。
  • c 按字符格式顯示變量。
  • f 按浮點數格式顯示變量。

仍是以輔助程序來講明,正常方式打印字符數組c:

(gdb) p c
$18 = "hello,shouwang"

可是若是咱們要查看它的十六進制格式打印呢?

(gdb) p/x c
$19 = {0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x73, 0x68, 0x6f, 0x75, 0x77, 0x61, 
  0x6e, 0x67, 0x0}
(gdb)

可是若是咱們想用這種方式查看浮點數的二進制格式是怎樣的是不行的,由於直接打印它首先會被轉換成整型,所以最終會獲得8:

(gdb) p e
$1 = 8.5
(gdb) p/t e
$2 = 1000
(gdb) 

那麼就須要另一種查看方式了。

查看內存內容

examine(簡寫爲x)能夠用來查看內存地址中的值。語法以下:

x/[n][f][u] addr

其中:

  • n 表示要顯示的內存單元數,默認值爲1
  • f 表示要打印的格式,前面已經提到了格式控制字符
  • u 要打印的單元長度
  • addr 內存地址

單元類型常見有以下:

  • b 字節
  • h 半字,即雙字節
  • w 字,即四字節
  • g 八字節

咱們經過一個實例來看,假如咱們要把float變量e按照二進制方式打印,而且打印單位是一字節:

(gdb) x/4tb &e
0x7fffffffdbd4:    00000000    00000000    00001000    01000001
(gdb) 

能夠看到,變量e的四個字節都以二進制的方式打印出來了。

自動顯示變量內容

假設咱們但願程序斷住時,就顯示某個變量的值,可使用display命令。

(gdb) display e
1: e = 8.5

那麼每次程序斷住時,就會打印e的值。要查看哪些變量被設置了display,可使用:

(gdb)info display
Auto-display expressions now in effect:
Num Enb Expression
1:   y  b
2:   y  e

若是想要清除可使用

delete display num #num爲前面變量前的編號,不帶num時清除全部。

或者去使能:

disable display num  #num爲前面變量前的編號,不帶num時去使能全部

微信公衆號【編程珠璣】:專一但不限於分享計算機編程基礎,Linux,C語言,C++,算法,數據庫等編程相關[原創]技術文章,號內包含大量經典電子書和視頻學習資源。歡迎一塊兒交流學習,一塊兒修煉計算機「內功」,知其然,更知其因此然。

公衆號編程珠璣公衆號編程珠璣

查看寄存器內容

(gdb)info registers
rax            0x0    0
rbx            0x0    0
rcx            0x7ffff7dd1b00    140737351850752
rdx            0x0    0
rsi            0x7ffff7dd1b30    140737351850800
rdi            0xffffffff    4294967295
rbp            0x7fffffffdc10    0x7fffffffdc10
(內容過多未顯示徹底)

總結

經過不一樣方式查看變量值或者內存值可以極大的幫助咱們判斷程序的運行是否符合咱們的預期,若是發現觀察的值不是咱們預期的時候,就須要檢查咱們的代碼了。

相關文章
相關標籤/搜索