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

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>
            欧美激情一区二区三区在线视频观看| 欧美国产日韩a欧美在线观看| 国产亚洲一区二区三区在线播放| 99国产精品自拍| 国产精品久久久久aaaa| 欧美精品日韩一区| 欧美日韩一区二区三区在线看| 欧美日韩综合在线| 国产精品看片资源| 国产精品一卡二| 国自产拍偷拍福利精品免费一| 在线观看日韩av| 日韩一级网站| 欧美一区二区三区视频在线 | 久久综合九色欧美综合狠狠| 欧美激情一区二区三区蜜桃视频| 亚洲国产精品一区二区尤物区| 欧美国产日产韩国视频| 一本色道**综合亚洲精品蜜桃冫| 亚洲午夜91| 毛片基地黄久久久久久天堂| 欧美视频网站| 亚洲大片免费看| 亚洲女女女同性video| 美女尤物久久精品| 亚洲视频一二| 嫩草国产精品入口| 国产视频久久网| 99精品久久免费看蜜臀剧情介绍| 久久精品日产第一区二区三区 | 欧美怡红院视频一区二区三区| 蜜桃精品久久久久久久免费影院| 亚洲精品日韩在线观看| 欧美亚洲自偷自偷| 欧美日韩中文字幕精品| 亚洲国产精品视频一区| 欧美一级淫片aaaaaaa视频| 亚洲娇小video精品| 久久久久久久久久看片| 欧美三区视频| 亚洲另类自拍| 欧美成人精品福利| 午夜在线视频一区二区区别| 国产精品sss| 一区二区三区四区五区在线| 欧美激情中文不卡| 久久久久久9| 国产一区欧美| 欧美中在线观看| 亚洲欧美日韩精品综合在线观看| 欧美午夜精品久久久久久浪潮| 亚洲精品乱码| 欧美电影打屁股sp| 久久精品欧美日韩精品| 国产亚洲成人一区| 西西裸体人体做爰大胆久久久| 亚洲欧美另类久久久精品2019| 9色porny自拍视频一区二区| 免费不卡在线观看| 欧美专区一区二区三区| 国产欧美日韩在线观看| 亚洲欧美电影在线观看| 亚洲桃色在线一区| 国产精品午夜在线| 性做久久久久久久免费看| 99精品视频一区| 欧美天堂亚洲电影院在线播放| 亚洲最新色图| 亚洲精品美女| 国产精品高潮呻吟久久| 午夜精品视频在线| 亚洲男女毛片无遮挡| 国产欧美一区二区在线观看| 久久精品中文字幕免费mv| 性欧美精品高清| 在线激情影院一区| 亚洲国产美女久久久久| 欧美人在线观看| 午夜在线视频一区二区区别| 欧美一区深夜视频| 亚洲欧洲日产国产网站| 亚洲美女在线观看| 国产精品影视天天线| 久久露脸国产精品| 欧美电影美腿模特1979在线看| 日韩一级大片在线| 亚洲男女自偷自拍图片另类| 国内精品久久久久影院薰衣草| 欧美激情在线免费观看| 国产精品免费看片| 亚洲第一在线综合网站| 欧美视频免费在线| 农夫在线精品视频免费观看| 欧美精品导航| 欧美一级午夜免费电影| 欧美成人午夜激情在线| 欧美在线看片| 欧美日韩精品免费在线观看视频| 久久国产毛片| 欧美日韩成人综合天天影院| 久久五月激情| 国产精品久久久免费| 欧美岛国激情| 国产欧美一级| 一区二区三区导航| 亚洲国产视频一区| 午夜在线观看免费一区| 在线一区二区三区四区五区| 久久久久久久久久久久久9999 | 久久综合婷婷| 国产精品久久久一区麻豆最新章节| 狼人社综合社区| 国产精品一区亚洲| 亚洲伦理在线| 日韩午夜剧场| 久久久久久9| 久久亚洲风情| 国产日韩av一区二区| 日韩小视频在线观看| 欧美激情免费在线| 一区二区在线观看视频| 亚洲综合视频在线| 一区二区三区黄色| 欧美1区2区视频| 麻豆成人av| 激情久久综艺| 久久精品视频网| 久久久久久久久久久一区 | 最新高清无码专区| 在线观看欧美一区| 久久精品国产第一区二区三区最新章节 | 99精品热6080yy久久| 日韩午夜在线播放| 欧美日本三级| 日韩视频免费| 亚洲小少妇裸体bbw| 欧美日韩中文字幕| 亚洲网站视频| 欧美在线视屏 | 亚洲视频在线观看网站| 欧美日韩一区在线播放| 99精品福利视频| 亚洲欧美激情精品一区二区| 国产精品大片wwwwww| 亚洲影院色无极综合| 久久久999| 91久久中文| 国产精品黄视频| 欧美在线观看一二区| 毛片基地黄久久久久久天堂 | 久久本道综合色狠狠五月| 国产欧美一区二区三区国产幕精品 | 亚洲免费成人av电影| 欧美大片一区二区| 亚洲精品资源美女情侣酒店| 亚洲自拍偷拍一区| 亚洲欧美欧美一区二区三区| 国产区在线观看成人精品| 久久国产福利国产秒拍| 亚洲国产精品www| 亚洲欧美综合精品久久成人 | 欧美日韩国产影院| 亚洲天堂成人| 美女主播视频一区| 亚洲图片激情小说| 国产亚洲欧美一级| 欧美国产一区二区三区激情无套| 一本色道久久综合亚洲精品婷婷| 久久国产欧美日韩精品| 亚洲国产欧美一区| 欧美日韩在线视频观看| 久久黄色网页| 99亚洲一区二区| 快she精品国产999| 亚洲最黄网站| 在线观看av不卡| 国产精品国产三级国产aⅴ9色| 亚洲综合电影| 黄色成人在线观看| 久久免费偷拍视频| 一区二区三区日韩精品视频| 久久午夜视频| 亚洲一区二区伦理| 激情久久影院| 国产精品视区| 欧美精品一区二区精品网| 欧美一区二区在线免费观看| 亚洲免费成人av| 欧美电影电视剧在线观看| 亚洲欧美国产va在线影院| 亚洲欧洲偷拍精品| 激情视频一区二区三区| 国产精品嫩草影院av蜜臀| 欧美久久电影| 免费在线欧美黄色| 久久久另类综合| 久久精品女人的天堂av| 亚洲欧美综合网| 亚洲一级二级| 亚洲一区二区三区欧美|