【正文】
ble), 提供調(diào)試信息 。 首先使用 gcc –g –o example1 代碼進(jìn)行編譯,這樣就可以使用 gdb監(jiān)視example1的執(zhí)行細(xì)節(jié)。在 bash提示符下,鍵入命令 :gdb example1, 啟動了對可執(zhí)行文件example1 的調(diào)試,在屏幕上會出現(xiàn)下面的信息: [nie@uClinux nie]$ gdb example1 GNU gdb Red Hat Linux () (MI_OUT) Copyright 2021 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are wele to change it and/or distribute copies of it under certain conditions. Type show copying to see the conditions. There is absolutely no warranty for GDB. Type show warranty for details. This GDB was configured as i386redhatlinux... (gdb) 最后一行 (gdb)就是進(jìn)入到 gdb調(diào)試中的提示符,此時可以在提示符下輸入任何想鍵入的命令。 現(xiàn)在如果要進(jìn)行斷點調(diào)試的話,就需要顯示一下要調(diào)試的源碼,以便知道在哪個地方進(jìn)行斷點設(shè)置。在 gdb下,Linux最常用文本編輯命令 vi不能使用,可以使用 list命令列出可執(zhí)行文件的源代碼的一部分,為了列出源代碼的全部,只要多鍵入幾次 list命令即可。具體操作如下 : (gdb) list 屏幕上清楚顯示出了每一個語句所在的具體行號 ,比如現(xiàn)在我們想在第五行設(shè)置斷點 , 可以在 gdb提示符下輸入命令: break 5, 可以看到下面的顯示信息: (gdb) break 5 Breakpoint 1 at 0x8048466: file , line 5. 斷點已經(jīng)設(shè)置好 , 現(xiàn)在開始讓程序運行起來 , 鍵入命令 run, 也可以鍵入其縮寫形式 r, 屏幕上出現(xiàn)的信息如下: (gdb) r Starting program: /home/nie/example1 Breakpoint 1, main () at :5 5 int x = 5。 上述信息表明 , gdb已經(jīng)開始執(zhí)行可執(zhí)行程序 , 目前程序運行到 程序中 main()函數(shù)的第五行處停止 , 并且顯示出即將要執(zhí)行的第五行語句 。 現(xiàn)在我們進(jìn)行單步調(diào)試的工作 , 輸入命令: next, 它表明單步執(zhí)行程序的每一條語句 , 當(dāng)用 next命令執(zhí)行到函數(shù) display處時 , 即當(dāng)屏幕出現(xiàn)如下所示信息時: (gdb) next 6 int *xptr = amp。x。 (gdb) next 7 printf(In main():\n)。 (gdb) next In main(): 8 printf( x is %d and is stored at %p.\n, x, amp。x)。 (gdb) next x is 5 and is stored at 0xbffffb44. 9 printf( xptr holds %p and points to %d.\n, xptr, *xptr)。 (gdb) next xptr holds 0xbffffb44 and points to 5. 10 display(x, xptr)。 為了進(jìn)入到函數(shù) display內(nèi)部進(jìn)行調(diào)試 , 輸入命令 step, 即: (gdb) step display (z=5, zptr=0xbffffb44) at :15 15 printf(In display():\n)。 step命令使執(zhí)行進(jìn)入到函數(shù)內(nèi)部 , 此時在該函數(shù)內(nèi)部 , 可以繼續(xù)使用 step命令或者是 next命令進(jìn)行單步執(zhí)行 , 如果不想單步執(zhí)行 , 而是直接將程序一次執(zhí)行完畢 , 可以輸入命令continue即可 。 要退出 gdb, 請鍵入命令 quit, 如果程序此時仍在進(jìn)行 ,gdb會讓你確認(rèn)是否真的要退出 , 屏幕會出現(xiàn)類似下面的提示信息: (gdb) quit The program is running. Exit anyway? (y or n) 按下 ‘ y’即退出調(diào)試程序,如果程序本身已經(jīng)運行完畢,則quit命令鍵入后,會直接退出 gdb,而不出現(xiàn)任何提示信息 。 關(guān)于內(nèi)存對齊的問題 include pragma pack(push,1) struct s1{ int i。 int j。 char c。 } s_1。 pragma pack(pop) struct s2{ int i。 int j。 char c。 } s_2。 int main() { = 0x49424344。 = 0x45464748。 = 39。c39。 printf(\nTest for struct s1\nsize \t%d\n,sizeof(s_1))。 fwrite(amp。s_1,sizeof(s_1),1,stdout)。 fflush(stdout)。 = 0x494A4B4C。 = 0x4D4E4F50。 printf(\nTest for struct s2\nsize \t%d\n,sizeof(s_2))。 fwrite(amp。s_2,sizeof(s_2),1,stdout)。 fflush(stdout)。 return 0。 } gcc和 vc的結(jié)果是 9, 12, tc2的結(jié)果都是 5,因為 tc的 int是 2位的,對于 pc的開發(fā)問題不是很大,但是對于嵌入式開發(fā),必須考慮到內(nèi)存浪費的問題。 一般的編譯器要對內(nèi)存進(jìn)行對齊,在處理結(jié)構(gòu)體變量時 ,編譯器都會根據(jù)一定的設(shè)置將長短不同的成員變量的數(shù)據(jù)長度進(jìn)行對齊以加快內(nèi)存處理速度 ,這就可能造成程序的不同部分對內(nèi)存的處理出現(xiàn)錯誤 .如一個結(jié)構(gòu) struct a { char i。 int j。 }。 盡管 i只有一個字節(jié), j占 4個字節(jié),但編譯器可能為了對齊為 i分配 4個字節(jié),結(jié)果整個結(jié)構(gòu)是 8個字節(jié),這就是 4字節(jié)對齊的情況,而在編譯器設(shè)為單字節(jié)對齊時則正好是 5個字節(jié)。 Struct member alignment用以指定數(shù)據(jù)結(jié)構(gòu)中的成員變量在內(nèi)存中是按幾字節(jié)對齊的,根據(jù)計算機(jī)數(shù)據(jù)總線的位數(shù),不同的對齊方式存取數(shù)據(jù)的速度不一樣。這個參數(shù)對數(shù)據(jù)包網(wǎng)絡(luò)傳輸?shù)葢?yīng)用尤為重要,不是存取速度問題,而是數(shù)據(jù)位的精確定義問題,一般在程序中使用 pragma pack來指定。 在 Unix系統(tǒng) /GCC編譯器中, GCC/G++ : fpackstruct , 在 Visual C++ 中,使用 “ ZP1” 就可以讓編譯器對自定義結(jié)構(gòu)進(jìn)行單字節(jié)對齊,實際就是取消了對齊優(yōu)化。 如果效率非常重要,就盡量不要使用 pragma pack, 如果必須使用,也最好僅在需要的地方進(jìn)行設(shè)置。因此需要加 pack的地方一定要在定義結(jié)構(gòu)的頭文件中加,不要依賴命令行選項,因為如果很多人使用該頭文件,并不是每個人都知道應(yīng)該 pack。 這特別表現(xiàn)在為別人開發(fā)庫文件時,如果一個庫函數(shù)使用了 struct作為其參數(shù),當(dāng)調(diào)用者與庫文件開發(fā)者使用不同的 pack時,就會造成錯誤,而且該類錯誤很不好查。 如果進(jìn)行網(wǎng)絡(luò)程序的開發(fā),考慮的不同 CPU之間的通信,最好設(shè)置為 字節(jié)對齊,會減少很多麻煩。