【正文】
ble), 提供調(diào)試信息 。 首先使用 gcc –g –o example1 代碼進(jìn)行編譯,這樣就可以使用 gdb監(jiān)視example1的執(zhí)行細(xì)節(jié)。在 bash提示符下,鍵入命令 :gdb example1, 啟動(dòng)了對(duì)可執(zhí)行文件example1 的調(diào)試,在屏幕上會(huì)出現(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)試中的提示符,此時(shí)可以在提示符下輸入任何想鍵入的命令。 現(xiàn)在如果要進(jìn)行斷點(diǎn)調(diào)試的話(huà),就需要顯示一下要調(diào)試的源碼,以便知道在哪個(gè)地方進(jìn)行斷點(diǎn)設(shè)置。在 gdb下,Linux最常用文本編輯命令 vi不能使用,可以使用 list命令列出可執(zhí)行文件的源代碼的一部分,為了列出源代碼的全部,只要多鍵入幾次 list命令即可。具體操作如下 : (gdb) list 屏幕上清楚顯示出了每一個(gè)語(yǔ)句所在的具體行號(hào) ,比如現(xiàn)在我們想在第五行設(shè)置斷點(diǎn) , 可以在 gdb提示符下輸入命令: break 5, 可以看到下面的顯示信息: (gdb) break 5 Breakpoint 1 at 0x8048466: file , line 5. 斷點(diǎn)已經(jīng)設(shè)置好 , 現(xiàn)在開(kāi)始讓程序運(yùn)行起來(lái) , 鍵入命令 run, 也可以鍵入其縮寫(xiě)形式 r, 屏幕上出現(xiàn)的信息如下: (gdb) r Starting program: /home/nie/example1 Breakpoint 1, main () at :5 5 int x = 5。 上述信息表明 , gdb已經(jīng)開(kāi)始執(zhí)行可執(zhí)行程序 , 目前程序運(yùn)行到 程序中 main()函數(shù)的第五行處停止 , 并且顯示出即將要執(zhí)行的第五行語(yǔ)句 。 現(xiàn)在我們進(jìn)行單步調(diào)試的工作 , 輸入命令: next, 它表明單步執(zhí)行程序的每一條語(yǔ)句 , 當(dāng)用 next命令執(zhí)行到函數(shù) display處時(shí) , 即當(dāng)屏幕出現(xiàn)如下所示信息時(shí): (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í)在該函數(shù)內(nèi)部 , 可以繼續(xù)使用 step命令或者是 next命令進(jìn)行單步執(zhí)行 , 如果不想單步執(zhí)行 , 而是直接將程序一次執(zhí)行完畢 , 可以輸入命令continue即可 。 要退出 gdb, 請(qǐng)鍵入命令 quit, 如果程序此時(shí)仍在進(jìn)行 ,gdb會(huì)讓你確認(rèn)是否真的要退出 , 屏幕會(huì)出現(xiàn)類(lèi)似下面的提示信息: (gdb) quit The program is running. Exit anyway? (y or n) 按下 ‘ y’即退出調(diào)試程序,如果程序本身已經(jīng)運(yùn)行完畢,則quit命令鍵入后,會(huì)直接退出 gdb,而不出現(xiàn)任何提示信息 。 關(guān)于內(nèi)存對(duì)齊的問(wèn)題 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,因?yàn)?tc的 int是 2位的,對(duì)于 pc的開(kāi)發(fā)問(wèn)題不是很大,但是對(duì)于嵌入式開(kāi)發(fā),必須考慮到內(nèi)存浪費(fèi)的問(wèn)題。 一般的編譯器要對(duì)內(nèi)存進(jìn)行對(duì)齊,在處理結(jié)構(gòu)體變量時(shí) ,編譯器都會(huì)根據(jù)一定的設(shè)置將長(zhǎng)短不同的成員變量的數(shù)據(jù)長(zhǎng)度進(jìn)行對(duì)齊以加快內(nèi)存處理速度 ,這就可能造成程序的不同部分對(duì)內(nèi)存的處理出現(xiàn)錯(cuò)誤 .如一個(gè)結(jié)構(gòu) struct a { char i。 int j。 }。 盡管 i只有一個(gè)字節(jié), j占 4個(gè)字節(jié),但編譯器可能為了對(duì)齊為 i分配 4個(gè)字節(jié),結(jié)果整個(gè)結(jié)構(gòu)是 8個(gè)字節(jié),這就是 4字節(jié)對(duì)齊的情況,而在編譯器設(shè)為單字節(jié)對(duì)齊時(shí)則正好是 5個(gè)字節(jié)。 Struct member alignment用以指定數(shù)據(jù)結(jié)構(gòu)中的成員變量在內(nèi)存中是按幾字節(jié)對(duì)齊的,根據(jù)計(jì)算機(jī)數(shù)據(jù)總線的位數(shù),不同的對(duì)齊方式存取數(shù)據(jù)的速度不一樣。這個(gè)參數(shù)對(duì)數(shù)據(jù)包網(wǎng)絡(luò)傳輸?shù)葢?yīng)用尤為重要,不是存取速度問(wèn)題,而是數(shù)據(jù)位的精確定義問(wèn)題,一般在程序中使用 pragma pack來(lái)指定。 在 Unix系統(tǒng) /GCC編譯器中, GCC/G++ : fpackstruct , 在 Visual C++ 中,使用 “ ZP1” 就可以讓編譯器對(duì)自定義結(jié)構(gòu)進(jìn)行單字節(jié)對(duì)齊,實(shí)際就是取消了對(duì)齊優(yōu)化。 如果效率非常重要,就盡量不要使用 pragma pack, 如果必須使用,也最好僅在需要的地方進(jìn)行設(shè)置。因此需要加 pack的地方一定要在定義結(jié)構(gòu)的頭文件中加,不要依賴(lài)命令行選項(xiàng),因?yàn)槿绻芏嗳耸褂迷擃^文件,并不是每個(gè)人都知道應(yīng)該 pack。 這特別表現(xiàn)在為別人開(kāi)發(fā)庫(kù)文件時(shí),如果一個(gè)庫(kù)函數(shù)使用了 struct作為其參數(shù),當(dāng)調(diào)用者與庫(kù)文件開(kāi)發(fā)者使用不同的 pack時(shí),就會(huì)造成錯(cuò)誤,而且該類(lèi)錯(cuò)誤很不好查。 如果進(jìn)行網(wǎng)絡(luò)程序的開(kāi)發(fā),考慮的不同 CPU之間的通信,最好設(shè)置為 字節(jié)對(duì)齊,會(huì)減少很多麻煩。