這篇是上星期的上課內容,我又拖了超過一個禮拜
因為不知為何這次上課速度非常快,教的東西又很雜
而我又很懶(毆)
不過不能再拖了,因為我現在能做的也只有讀書了
===
ch 10 除錯(Debugging)
===
《錯誤的種類》
Specification errors - 模型錯誤(如漏掉變數)
design error - 設計錯誤(沒有做好規劃)
coding error - 程式錯誤(寫程式寫錯了)
-> dry running - 把所有組合放進去測試
我們這次要來學習使用electric fence來除錯
一般應該要先打upd更新軟體清單
不過因為這套軟體幾乎都不更新
所以可以直接輸入ins electric-fence安裝
(記得安裝軟體要先切換root權限)
‧debug1
執行完卻發現什麼東西都沒有顯示,不知道他有沒有錯
輸入diff debug1.c debug2.c比較一下兩個範例
原來debug2多了顯示出來的程式碼
‧debug2
顯示了sort完的結果,不過答案是錯的...
因為系統一次給你一個block
‧debug3
比較一下就知道,差別在data直接給他4k記憶體
《修改系統語言為英文》
輸入以下指令
export LC_ALL='POSIX' - 全部改成POSIX
export LANG="C"
輸入locale看設定有沒有被改掉吧
《Debug相關語法》
‧DEBUG mode才做
用#ifdef DEBUG跟#endif將程式包起來
#ifdef DEBUG
printf(“variable x has value = %d\n”, x);
#endif
‧程式執行時給他debug值(1~7)
#define BASIC_DEBUG 1
#define EXTRA_DEBUG 2
#define SUPER_DEBUG 4 - 超詳細的錯誤內容
#if (DEBUG & EXTRA_DEBUG) //如果是Extra Debug才顯示
printf...
#endif
‧如果沒有debug值就給他0
#ifndef DEBUG
#define DEBUG 0
#endif
‧如果覺得每次修改完都要重新compile很麻煩
改成這樣即可
if (debug) {
sprintf(msg, ...)
write_debug(msg)
}
記得編譯時加上-DDEBUG參數,才是真的在DEBUG喔
《用gdb來Debug》
Segmentation fault是記憶體配置問題,通常發生在pointer身上
輸入gdb debug3開始偵錯
以下是在gdb模式下的指令
‧help - 顯示所有說明
註:用Ctrl+L可將畫面消掉
‧run - 開始執行程式,發現第23行有問題
‧backtrace - 查看函數呼叫堆疊
‧print j - 顯示變數j內容
‧print a[$-1].key - $指的是上一次最後的值
‧list - 把目前中斷的點放在中間
再輸入list會繼續往下看
‧list 10 - 把第十行放在中間
‧quit - 離開
問題出在 j=4
printf a[4] 正確
printf a[5] 錯誤
所以問題出在5超過範圍(原來是超基本的錯誤...)
‧debug4
可以顯示但是結果還是錯了
‧break 20 - 設中斷點停在第20行
‧print a[0]@5 - 顯示陣列下五個內容
‧display a[0]@5 - 每次碰到中斷點就做後面的事
‧cont - 繼續執行
還不懂的話可以輸入info display、info break查看說明
寫了這麼多,請讓我說句中肯的話,一句就好
以上都是怪胎用的,深受古代程式餘毒
現在都21世紀了,誰還會慢慢輸入中斷點用這種方式debug啊
請改用CodeBlock(其實我比較喜歡輕巧的dev-c++)
《用CodeBlock來Debug》
先開啟empty專案
開啟完後,在專案上按右鍵選擇Add files...
增加ch10/debug4.c這個檔案
並請在Debug跟Release的按鈕上打勾再按OK
先編譯,然後在21行設定中斷點(行號上按一下出現紅點即可)
選擇功能表的[debug]-[debuggubg windows]-[watch]
開啟Debug視窗,可以看變數內容
選擇[debug]-[start]來用debug模式執行
不過因為那時候老師也是弄的2266...所以也弄不出什麼好的東西
我放棄用CodeBlock來偵錯了...orz
《其他Debug工具》
‧Lint
會詳細跟你說程式可能會有什麼問題
ins splint - 安裝lint
splint debug3.c - 執行方式
‧ctags
產生原始碼每個tag(函數或變數名)的所在位置
執行後會產生tags這個檔案,可參考每一個tag的資訊
不過好像只支援vim這個編輯器...
apt-cache search ctags - 如果你不知道ctags的安裝名稱,請先搜尋
ins exuberant-ctags - 安裝ctags
ctags *.c - 目錄下產生一個tags檔案
cat tags - 看其內容
老實說我覺得不是很好用...
‧chref
其實我不知道他是要幹嘛的,老師沒有說清楚
好像跟上面那個程式差不多
dpkg-reconfigure cxref - 第一次執行請先讓他自動設定
cxref *.c - 執行
‧cflow
分析你的程式,看程式那個地方花多少時間
gcc -pg -o debug4 debug4.c - 編譯
./debug4 - 執行程式後目錄下會產生gmon.out
gprof debug4 gmon.out -p - 產生統計表
gprof debug4 gmon.out -q - 產生相關聯的呼叫
《其他範例教學》
‧assert
原始碼內有一段
assert(x >= 0.0);
代表x沒達成>=0的條件就會印出訊息
編譯時多加Don't debug
gcc -o assert -DNDEBUG assert.c -lm
assert部分就不會執行,不用把assert砍掉
‧efence
gcc -o efence efence.c
./efence
不會顯示任何問題,但其實有問題
gcc -o efence efence.c -lefence
./efence
改用此行編譯再執行就會發現問題
‧checker
去執行也看似沒問題
apt-get install valgrind
valgrind --leak-check=yes -v ./checker
應該就會出現問題了(我懶的試了=__=)
===
ch 11 程序(Process)
===
‧ps - 可以顯示目前的東西
‧pstree - 樹狀顯示
‧pstree -p - 加上process id
‧ps -l 跟ls -l一樣會顯示很多資訊
‧ps -ef - 會發現所有程式都是由init產生的
他是所有程式的祖先
‧ps aux - 目前所有process的狀態是什麼
‧oclock & - 執行oclock這個程式
‧nice oclock & - 加了nice代表讓他在背景執行
‧diff system1.c system2.c
system1跟system2差別只在一個會等他跑完一個不會罷了
system1加上以下幾行
int pid;
pid = getpid();
printf("My pid=%d\n",pid);
執行時有看到process id,程式執行完就沒了
‧pexec
一樣加上以下幾行,但printf那一行在前頭跟後面都加上來測試
int pid;
pid = getpid();
printf("My pid=%d\n",pid);
執行後卻發現最後那個printf沒有顯示出來
因為pexec會把自己的process蓋掉
所以後面的成事都做不到了
‧fork
簡單講就是把自己一分為二(複製一份自己),下次上課有較詳細的內容
三個禮拜之後要交作業
其實作業最簡單的話只要寫三行就好
char cmd[256];
gets(cmd);
system(cmd);
不過老師規定不可以用system要用fork
請搜尋man exec、man fork、man dup查看說明
好康道相報
※欲轉貼本站文章者,只要註明出處及網址即可,不需我同意了,謝謝您的配合
※留悄悄話的網友請注意:如果您非痞客邦會員(包含使用FB/Google+帳號),是看不到回覆的喔
※痞客邦會自動將疑似廣告留言隱藏,因此若留言後看不到,可能是被系統自動隱藏了,由於我現在很久才會開一次網誌,有看到時我才會將非廣告留言解開,敬請見諒
※留悄悄話的網友請注意:如果您非痞客邦會員(包含使用FB/Google+帳號),是看不到回覆的喔
※痞客邦會自動將疑似廣告留言隱藏,因此若留言後看不到,可能是被系統自動隱藏了,由於我現在很久才會開一次網誌,有看到時我才會將非廣告留言解開,敬請見諒
- Nov 30 Sun 2008 16:13
Linux程設學習筆記(十一)
全站熱搜
留言列表