MySQL源码学习——DBUG调试
一、前言
???????? 在規(guī)模稍微大點(diǎn)的項(xiàng)目中,為了方便快速找到bug的所在,我們往往需要在代碼中加入一些調(diào)試用的代碼,比如加入一些printf,打印出一些重點(diǎn)的信息;加入assert,進(jìn)行斷言判斷。這些比較隨意的調(diào)試代碼會(huì)使整個(gè)系統(tǒng)顯得比較凌亂。于是Fred Fish開(kāi)發(fā)了一套用于嵌入代碼中的庫(kù),開(kāi)發(fā)人員只需要調(diào)用相應(yīng)的函數(shù)即可加入調(diào)試信息。
??????? 對(duì)于MySQL這種多線程的程序來(lái)說(shuō),調(diào)試也是比較困難的,MySQL選擇了DBUG作為其調(diào)試代碼(在原始代碼的基礎(chǔ)上進(jìn)行了略微的改造),充分說(shuō)明了DBUG的實(shí)用性,本文就DBUG的原始代碼進(jìn)行介紹。
二、DBUG下載與使用
?????? 這里以linux下的開(kāi)發(fā)進(jìn)行介紹。
????? 首先需要下載DBUG源碼,下載地址:http://sourceforge.net/projects/dbug/
????? 解壓后在dbug/src下即是debug所需的源碼文件:dbug.h dbug.c
????? dbug/example.c是一個(gè)簡(jiǎn)單的例子,源碼如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | /* ?* This file is Public Domain ?* ?* Just short example, how Fred Fish's dbug package should be used ?* ?* Tonu Samuel <tonu @spam.ee=""> ?* ?*/ #include "dbug.h" static?int?sub1 (void); static?void?sub2 (char?*arg); static?int sub1 (void) { ??DBUG_ENTER ("sub1"); ??sub2 ("Hello world!"); ??sub2 ("Hello earth!"); ??sub2 ("Hello programmer!"); ??DBUG_RETURN (0); } static?void sub2 (char?*arg) { ??DBUG_ENTER ("sub2"); ??DBUG_PRINT ("info", ("Got argument: '%s'", arg)); ??printf?("%s\n", arg); ??DBUG_VOID_RETURN; } int main (void) { ??int?ret = 0; ??DBUG_PUSH ("d:t:O"); ??DBUG_PROCESS ("example"); ??ret = sub1 (); ??DBUG_PRINT ("info", ("Returned value: %d", ret)); ??return?0; }</tonu> |
我們將example.c放到src目錄下,然后編譯example文件:
| 1 | dbug/src$?gcc?-Wall -g dbug.c example.c -o example |
運(yùn)行example輸出如下:
| 1 2 3 4 5 6 7 8 9 10 11 | >sub1 | >sub2 | | info: Got argument:?'Hello world!' Hello world! | <sub2 |="">sub2 | | info: Got argument:?'Hello earth!' Hello earth! | <sub2 |="">sub2 | | info: Got argument:?'Hello programmer!' Hello programmer! | <sub2 pre=""?0="">< value: Returned info: <sub1></sub1></sub2></sub2></sub2> |
函數(shù)sub1調(diào)用了三次sub2,三次的參數(shù)分別是'Hello world!' ,'Hello earth!' ,'Hello programmer!' ,最后return 0.
???????? 下面初略介紹下上面用到的幾個(gè)宏定義:
DBUG_PUSH ("d:t:O");? 設(shè)置調(diào)試的啟動(dòng)參數(shù),參數(shù)列表在MySQL手冊(cè)上也有:
| 標(biāo)記 | 描述 |
| d | 允許對(duì)當(dāng)前狀態(tài)從DBUG_<N>宏輸出??赡芨涣嘘P(guān)鍵詞,這些關(guān)鍵詞僅對(duì)那些帶有? |
| D | 在每個(gè)調(diào)試起輸出行后延遲。參量一個(gè)十分之一秒為單位來(lái)延遲的數(shù),它受限于機(jī)器的能? |
| f | 限制調(diào)試和/或跟蹤,以及簡(jiǎn)單設(shè)定于列出名字的函數(shù)。注意,空列將禁止所用函數(shù)。應(yīng)? |
| F | 對(duì)調(diào)試或跟蹤輸出的每一行識(shí)別源文件名。 |
| i | 對(duì)調(diào)試或跟蹤輸出的每一行用PID或線程ID識(shí)別進(jìn)程。 |
| g | 允許解析,創(chuàng)建名為的dbugmon.out文件,它包含可用來(lái)簡(jiǎn)單設(shè)定程序的信息。可能跟著? |
| L | 為調(diào)試或跟蹤輸出的每一行識(shí)別源文件行號(hào)。 |
| n | 為調(diào)試或跟蹤輸出的每一行打印當(dāng)前函數(shù)嵌套深度。 |
| N | 給調(diào)試輸出的每一行編號(hào)。 |
| o | 重定向調(diào)試器輸出流到指定文件。默認(rèn)輸出是stderr 文件。 |
| O | 類似于 o,但是文件在每次寫操作之間被沖刷。當(dāng)需要之時(shí),文件在每次寫操作之間被關(guān)? |
| p | 限制調(diào)試器作用于指定進(jìn)程。為使調(diào)試器動(dòng)作,一個(gè)進(jìn)程必須用DBUG_PROCESS宏來(lái)識(shí)? |
| P | 為調(diào)試或跟蹤輸出的每一行打印當(dāng)前進(jìn)程名字。 |
| r | 當(dāng)推出一個(gè)新?tīng)顟B(tài)時(shí),不繼承前狀態(tài)的操作嵌套深度級(jí)別。當(dāng)輸出在左邊空白開(kāi)始時(shí)有? |
| S | 在每個(gè)調(diào)試過(guò)的函數(shù)做_sanity(_file_,_line_)函數(shù)直到 _sanity() 返回不同于0的結(jié)果。(大多? |
| t | 允許函數(shù)調(diào)用/退出跟蹤行。可能跟著一個(gè)給出最大跟蹤級(jí)別的數(shù)字列(只含一個(gè)修改? |
??????? DBUG_PROCESS ("example"); 設(shè)置進(jìn)程名為example
??????? DBUG_ENTER ("sub1"); 表示進(jìn)入函數(shù)sub1
??????? DBUG_PRINT ("info", ("Got argument: '%s'", arg)); 和printf效果差不多,打印出需要的調(diào)試信息。
?????? DBUG_RETURN (0);? 在return 0 的基礎(chǔ)上,打印出return 0的調(diào)試信息。
三、小結(jié)
????? 本文簡(jiǎn)單介紹了DBUG的使用方法,沒(méi)有深究,源碼很少,卻很實(shí)用,在源碼的注釋部分,我看到了是Fred Fish1987年寫的,呃,我才剛出生....,沒(méi)想到現(xiàn)在還在看那時(shí)候的代碼,可能這就是所謂的經(jīng)典吧。
?????? 兄弟們,你們還在為復(fù)雜環(huán)境下的bug調(diào)試而苦惱么?還在為堆棧被寫亂掉無(wú)從下手而凌亂么?淡定吧,一起來(lái)用DBUG吧~~
踏著落葉,追尋著我的夢(mèng)想。轉(zhuǎn)載請(qǐng)注明出處總結(jié)
以上是生活随笔為你收集整理的MySQL源码学习——DBUG调试的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Concurrent包工具类使用
- 下一篇: 常用 SQL 语句汇总