青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

S.l.e!ep.¢%

像打了激速一樣,以四倍的速度運轉,開心的工作
簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

GDB怎么調試運行著的程序

Posted on 2010-11-04 17:03 S.l.e!ep.¢% 閱讀(2779) 評論(0)  編輯 收藏 引用 所屬分類: Unix

GDB怎么調試運行著的程序

Posted by 機器人 on 10th 九月 2009 in c/c++, linux/server

對于GDB這里就不作介紹了,隨便找個搜索引擎一搜GDB,介紹就已經是很詳細了,這篇文章主要是來談怎么使用GDB來調試一個運行著的程序,或者說怎么調試一個進程,似乎標題有些拗口,其次也會對fork()分離出現的多子進程的調試加以說明。
下面是一段測試代碼。
test.c

										#include < stdio.h >
										#include < unistd.h >
?
staticvoid PrintMessage(int i);staticvoid GoToSleep(void);
?
?
int main(void){int i =100000;
?
	while(1){
		PrintMessage( i );
		GoToSleep();
		i -=1;}
?
	return0;}
?
?
?
void PrintMessage(int i){char buf[1024];
		sprintf(buf,"%d bottles of beer on the wall.\n", i);printf("%s",buf);
?
}
?
?
?
staticvoid GoToSleep(void){
	sleep(3);}

接下來是編譯時使用的Makefile文件.

TARGET = test
SRC    =  $(TARGET).c
OBJ    =  $(TARGET).o
CC     =  gcc
CFLAGS = -g3-W-Wall-std=c99
?
$(TARGET): $(OBJS)
?
?
.PHONY: clean
?
clean:
	$(RM) $(TARGET) $(OBJS)

此程序是一個服務程序,程序一旦啟動,將作為一個進程永駐內存,可以通過

~@hqlong ps-ef|grep"test"

來查看該進程的信息。
此程序主要實現每3秒鐘向墻上打印一瓶啤酒。對于這樣的一個啟動就作為一個進程進駐內存的程序應該怎么來進行調試呢?接下來的事情就是要來回來這個問題,
通過make來對源文件進行編譯。

~@hqlong make

這里會在當前目錄下產生一個test的可執行文件。
在對程序進行正式調試之前來回憶一個使用GDB調試一個非服務程序的步驟。假設test這個可執行文件是一個非服務程序,那么一般是通過如下幾步方式來進行調試的。

hqlong@ubuntu:/tmp$ gdbtest
GNU gdb6.8-debian
Copyright (C)2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http ://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty"for details.
This GDB was configured as"i486-linux-gnu"...
(gdb) b 1
Breakpoint 1 at 0x80483f4: file beer-process.c, line 1.
(gdb) r
Starting program: /tmp/test 
?
Breakpoint 1, main () at beer-process.c:9
warning: Source file is more recent than executable.
9{(gdb) n
main () at beer-process.c:1010		int i = 100000;
(gdb) q
The program is running.  Exit anyway? (y or n) y
</http>

首先是通過gdb test來調試程序。然后使用b(break) 1在第一行設置斷點,然后使用r(run) 來運行程序,最后使用n來單步運行程序,如果想要查看運行中某變量的值,可能通過p(print)來打印。如查看i的值,就可以通過p i。最后使用q(quit)來退出程序。

由于服務程序一旦啟動,就以進程的方式進駐內存,不退出,所以和非服務程序的調試方式有一些區別。
服務一旦啟動后,系統會分配一個pid,然后使用gdb綁定上這個pid,最后就可以通過通用方式進行調試了。
綁定進程的方式有下幾種。

hqlong@ubuntu:/tmp$ ./test&100000 bottles of beer on the wall.
[1]25292

方式一
通過–pid參數來綁定指定的進程程序。

~@hqlong gdb--pid25552

方式二
通過程序和進程號來綁定。

~@hqlong gdbtest25552

方式二
先啟動gdb后,通過attach來綁定pid

~@hqlong gdbgdb) attach 25552

將pid和gdb綁定后,就可以來對每一段代碼進行調試。
下面是對上面例子的完整調試過程。
1. 啟動進程

hqlong@ubuntu:/tmp$ ./test&[1]25615
hqlong@ubuntu:/tmp$ 100000 bottles of beer on the wall.
99999 bottles of beer on the wall.
99998 bottles of beer on the wall.

可以看見,啟動test后,系統所分配的pid(進程號)為25615,然后每隔3秒鐘就打印出一條信息。
2.使用gdb來綁定test進程。
這里需要重新啟動一個新的shell來進行調試,也就是新開一個窗口,然后使用

hqlong@ubuntu:/tmp$ gdb--pid25615
GNU gdb6.8-debian
Copyright (C)2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http ://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty"for details.
This GDB was configured as"i486-linux-gnu".
Attaching to process 25615
Reading symbols from /tmp/test...done.
Reading symbols from /lib/tls/i686/cmov/libc.so.6...done.
Loaded symbols for/lib/tls/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for/lib/ld-linux.so.2
0xb7ffb430 in __kernel_vsyscall ()(gdb)</http>

來將gdb與已啟動的test進行綁定,從而進入調試狀態,這里會發現,當進入gdb調試狀態后,先前啟動程序的窗口就不再每隔3秒鐘打印信息了,而是將控制權將給了gdb.
3.使用bt來顯示當前程序的函數調用棧結構(也就是函數的調用順序)。

										(
										gdb
										) bt
#0  0xb7ffb430 in __kernel_vsyscall ()#1  0xb7f23780 in nanosleep () from /lib/tls/i686/cmov/libc.so.6#2  0xb7f235be in sleep () from /lib/tls/i686/cmov/libc.so.6#3  0x0804851e in GoToSleep () at beer-process.c:35#4  0x080484ac in main () at beer-process.c:15(gdb)

可知函數的調用過程為:main調用GoToSleep,GoToSleep調用sleep等。
使用frame來選擇程序的調試起點,也可以使用break來選擇指定的行或者函數來作為斷點。

										(
										gdb
										) frame 4#4  0x080484ac in main () at beer-process.c:1515			GoToSleep();
(gdb)

這里我們選擇最底層的棧,也就是整個程序的入口main函數來作為起點。
4. 調試跟蹤過程
使用n(next)來一步一步的跟蹤。

										(
										gdb
										) n
Single stepping untilexit from functionsleep, 
which has no line number information.
GoToSleep () at beer-process.c:3636}(gdb) 
main () at beer-process.c:1616			i -= 1;
(gdb)14			PrintMessage( i );
(gdb)

這里有個技巧,如果要重復執行上一次執行的操作,可以直接回車。
通過上面的調試,發現程序運行到了14行,也就是PrintMessage函數處,如果這個時候我們繼續n(next),程序就直接跳過函數,運行到函數的下一行,但如果想進入函數內部去調試,可以使用s(step),來進入函數體內進行調試。
進入函數體

										(
										gdb
										)
										14			PrintMessage( i );
(gdb) s
PrintMessage (i=99897) at beer-process.c:2525{(gdb) n
27	    sprintf(buf,"%d bottles of beer on the wall.\n", i);
(gdb) n
28printf("%s",buf);
(gdb)

以上是進入PrintMessage體內,然后繼續使用n(next)來一步一步的運行。進行到了28行,發現有兩個變量,一個為i,另一個為buf,可以通過p(print)來打印該變量的值。

										(
										gdb
										) p i
$1 = 99897(gdb) p buf
$2 = "99897 bottles of beer on the wall.\n\000\000R\000?0u??????$u???\227\001?\000\000\000\000p???\000\000\000\000\000\000\000\000\001\000\000\000??DB?x??8???\000\000\000\000?\217\001?p\226\001?0u??$u???\226\000?\001\000\000\000\000\000\000\000?v???\222\001?\205???", '\0'<repeats 12times>, "?\226\000??\217\001?\000\000\000\000\000u???t???\020\001?\b\000\000\000\f\000\000\000\000????v??b\221\000?\000???\020???\f\000\000\000?\217"...
(gdb)</repeats>

發現通過p i 來打印i的值,結果是正確的,但通過p buf來打印buf 的值,卻顯示了很多不可讀的亂碼。這里因為buf代表這個變量在內存中的首地址,所以p不知道變量在什么時候結束,而i則不同,因為i是整型,在內存中一般占4個字節,所以p直接從首地址向后數4位就行了。所以這里打印字符指針或者數組時,需要指定一個長度。語法為 p *buf@len. 這里的len可以通過strlen(buf)來取得。

										(
										gdb
										) p *buf@strlen(buf)
$3 = "99897 bottles of beer on the wall.\n"(gdb)

這一下子就對了。
接下來繼續使用n(next)來單步運行。

										(
										gdb
										)
										28
										printf
										(
										"%s",buf);

發現運行到這一步時,啟動程序的那個窗口打印出了一條信息。

										99897 bottles of beer on the wall.

這說明,程序正好運行到了打印字符的地方。
如果這個時候想退出函數,直接返回,可能通過 finish.

										(
										gdb
										) finish 
Run till exit from #0  PrintMessage (i=99895) at beer-process.c:28
main () at beer-process.c:1515			GoToSleep();
(gdb)
退出PrintMessage函數,接著運行下一行代碼GoToSleep.
如果調試完畢,或能通過q(quit)來退出GDB。
										(
										gdb
										) q
The program is running.  Quit anyway (and detach it)? (y or n) y
Detaching from program: /tmp/test, process 25615

以上是調試一個進程的過程。

下面附帶說明一下怎么調試一個需要通過fork()分離進程的程序。下面是一段一個Web服務器的在接受請求時的代碼片斷。

										for
										(
										;;
										)
										{
										if
										(
										(connfd = accept(listenfd, (struct sockaddr *)&clientaddr,
					&clientaddrlen)) == -1){perror("http server: accept error");
		continue;
	}if(fork() == 0)
		accept_request(connfd);
	else close(connfd);
?
	int statloc;
	waitpid(-1, &statloc, WNOHANG);
}

當單步運行到if(fork() == 0)這一步時,那怕是分離進程成功,也不會運行accept_request(connfd);而是直接跳到跳過,運行下面的代碼。在調試這樣的程序里,需要在進入gdb控制臺時,需要將follow-fork-mode的值設成child.

										(
										gdb
										)
										set follow-fork-mode child

本文主要是體驗一下使用GDB的調試過程,對一些指令和俗語沒有作過多的解釋,如果有不明白可直接留言,或者參考相關資料。
參數資料
http://www.gnu.org/software/gdb/
http://dirac.org/linux/gdb/06-Debugging_A_Running_Process.php

結束

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美国产91| 在线观看中文字幕不卡| 欧美在线视频一区| 亚洲综合日韩| 欧美一级视频精品观看| 亚洲无吗在线| 久久激情五月丁香伊人| 欧美一激情一区二区三区| 久久精品成人| 欧美金8天国| 国产精品久久午夜夜伦鲁鲁| 国产精品尤物| 亚洲国产精品福利| 亚洲女人天堂成人av在线| 久久久久久久久久看片| 欧美激情成人在线| 亚洲免费影院| 免费短视频成人日韩| 国产精品99免费看| 一色屋精品视频在线看| 亚洲剧情一区二区| 久久国产精品72免费观看| 亚洲国产成人不卡| 亚洲一区在线免费| 欧美大胆人体视频| 国产亚洲综合在线| 亚洲激情在线| 欧美在线日韩| 美女图片一区二区| 国产欧美一区二区色老头| 亚洲人成欧美中文字幕| 欧美亚洲一级| 亚洲日韩欧美视频一区| 欧美一区二区三区在线播放| 欧美精品观看| 亚洲第一色中文字幕| 欧美亚洲日本国产| 一区二区三区成人精品| 久久一综合视频| 国产乱肥老妇国产一区二| 一本久道久久久| 91久久精品日日躁夜夜躁国产| 欧美在线免费观看| 国产欧美日韩一区| 欧美一级淫片aaaaaaa视频| 亚洲精品乱码久久久久久蜜桃91| 久久频这里精品99香蕉| 精品动漫一区| 免费av成人在线| 久久久久国产一区二区| 国产一区观看| 久久久精品国产99久久精品芒果| 亚洲综合三区| 国产精品一区一区| 欧美中文字幕视频在线观看| 亚洲一区二区精品在线| 欧美日韩一区二区三区四区在线观看| 最新成人av在线| 91久久综合亚洲鲁鲁五月天| 欧美a级一区二区| 亚洲欧洲精品天堂一级| 亚洲大胆女人| 国产主播一区二区三区| 篠田优中文在线播放第一区| 中文国产一区| 国产欧美日韩不卡免费| 欧美在线免费观看| 久久精品一区中文字幕| 亚洲第一精品夜夜躁人人爽| 欧美xxx在线观看| 欧美va亚洲va国产综合| 亚洲精品在线视频观看| 亚洲伦理精品| 国产精品三级久久久久久电影| 亚洲一区二区在线| 亚洲女人天堂av| 黄色成人在线| 91久久午夜| 国产精品久久久久久模特| 欧美一区二区三区视频在线| 久久精品一区二区三区不卡牛牛| 亚洲精品1区| 99视频精品免费观看| 国产精品久久福利| 久久久人成影片一区二区三区| 久久久精品网| 亚洲视频 欧洲视频| 在线免费不卡视频| 国产精品乱码妇女bbbb| 欧美一级久久久久久久大片| 香蕉精品999视频一区二区 | 亚洲国产精品一区二区www| 欧美激情久久久久久| 亚洲一区二区精品视频| 久久久久.com| 夜夜嗨av色一区二区不卡| 亚洲一区综合| 99re66热这里只有精品4 | 欧美日韩1080p| 久久久99精品免费观看不卡| 欧美成人精品三级在线观看| 欧美一区二区三区的| 欧美高清不卡| 久久久精品免费视频| 欧美理论大片| 欧美大片在线影院| 国产日韩一区欧美| 99亚洲伊人久久精品影院红桃| 国产亚洲在线| 亚洲一区二区毛片| 亚洲麻豆视频| 免费av成人在线| 久久人人爽人人爽| 国产精品视频你懂的| 99re国产精品| 99国产精品久久| 欧美成人午夜| 欧美国产日韩xxxxx| 韩国自拍一区| 久久国产精品网站| 久久激情久久| 国产精品亚洲激情| 一区二区三区免费网站| 一区二区三区四区五区在线| 欧美电影打屁股sp| 欧美国产综合一区二区| 伊人成人开心激情综合网| 久久精品91久久久久久再现| 久久福利资源站| 国产主播一区二区三区四区| 亚洲欧美中日韩| 久久久不卡网国产精品一区| 国产精品一区二区三区乱码 | 一本久久综合| 欧美激情欧美激情在线五月| 欧美激情精品久久久久久变态| 伊人久久亚洲热| 久久噜噜噜精品国产亚洲综合| 久久精品亚洲| 精品电影在线观看| 久久蜜臀精品av| 欧美成人午夜77777| 亚洲国产成人精品久久| 欧美大片在线观看一区| 亚洲精品小视频在线观看| 亚洲一二三级电影| 国产乱人伦精品一区二区| 欧美一级午夜免费电影| 国产精品久久久久91| 亚洲欧美在线aaa| 久久精品五月| 亚洲福利在线观看| 欧美国产激情二区三区| 亚洲美女黄色| 欧美在线视频观看| 在线免费观看日本一区| 欧美成人嫩草网站| 亚洲午夜激情网站| 猫咪成人在线观看| 在线视频精品一区| 国产字幕视频一区二区| 另类成人小视频在线| 亚洲精品一区二区三区蜜桃久| 亚洲综合首页| 亚洲高清不卡| 国产精品亚洲网站| 欧美成人精品在线| 亚洲在线观看视频网站| 欧美波霸影院| 午夜国产一区| 亚洲精品黄色| 国产精品日韩精品欧美精品| 久久久久久久一区二区| 日韩一区二区免费看| 免费日韩av电影| 午夜精品福利一区二区蜜股av| 在线观看国产成人av片| 国产精品卡一卡二| 欧美激情1区2区3区| 欧美在线国产| 亚洲一区亚洲| 亚洲精品中文字幕女同| 久久亚洲精品伦理| 亚洲欧美在线视频观看| 亚洲精品孕妇| 亚洲国产精品久久精品怡红院| 国产日韩成人精品| 欧美日韩在线另类| 欧美成人国产| 久久人人97超碰国产公开结果| 亚洲一区二区三区视频| 亚洲精品黄网在线观看| 欧美国产日韩xxxxx| 久久深夜福利| 久久久久久久999精品视频| 午夜在线视频观看日韩17c| 一区二区三区日韩欧美精品| 亚洲国产天堂久久国产91| 狠狠v欧美v日韩v亚洲ⅴ| 国产午夜精品一区二区三区视频|