1. 程式人生 > >實驗一:實驗環境配置與使用

實驗一:實驗環境配置與使用

png 黃色 變化 gdb調試 操作 分析 對比 spa -c

一、實驗目標:

熟悉Linux上C程序的編譯和調試工具,包括以下內容:

1. 了解Linux操作系統及其常用命令

2. 掌握編譯工具gcc的基本用法

3. 掌握使用gdb進行程序調試

二、實驗環境與工件

1.個人電腦

2. Fedora 13 Linux 操作系統

3. gcc

4. gdb

三、實驗內容與步驟

1.根據實驗一:實驗環境配置與使用.ppt熟悉Linux基本操作(P.1 – P.28),然後根據以下過程創建用戶:用戶名為學生名稱加學號,如賴丹輝,學號2013150040,則該用戶名為Laidanhui_2013150040。按照1.1~1.3完成並截圖,截圖需要有運行的命令及其結果。另外:後面的題目必須在該新建用戶下完成。

實驗步驟:

1.1.首先切換為超級用戶

在終端環境下,$su

技術分享技術分享

1.2. 參考以下命令創建新用戶, 設置新建用戶的密碼,註意:只有設置了密碼才能激活用戶,否則無法以該用戶身份登錄

#useradd (your name)

#passwd (your password)

技術分享

1.3. 註銷當前用戶,並以新建的用戶身份登錄,登錄後運行 $ whoami,並進行截圖;

技術分享

2.新建用戶主目錄下創建子目錄:gdbdebug, 並進入gdbdebug 子目錄。將過程和結果截圖。

先切換到超級用戶,然後使用mkdir命令在home/XuXianyuan_2015150147目錄下創建gdbdebug子目錄,再使用ls顯示該目錄下內容,黃色部分結果表示創建成功。

技術分享

進入gdbdebug目錄下:

技術分享

進入成功。

3.使用vi編輯以下兩個文件並編譯和運行,截圖

3.1.編輯reverse.h

最後在最後使用:wq保存並退出

技術分享

在gdbdebug目錄下使用ls命令:(黃色標註部分表示reverse.h文件創建成功。)

技術分享

3.2.編輯reverse.c

技術分享

3.3.按以下步驟編譯,如有警告信息,請修改代碼至無警告信息

$gcc –Wall reverse.c –o reverse:生成的所有警告信息如下圖所示:

技術分享

分析相應的警告信息:

第一條:隱式聲明函數‘strlen’,很明顯沒有包含相應頭文件,故只需在reverse.c中 添加頭文件<string.h>即可。

第二條:格式 ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[1024]’,這個警告是說輸入格式不對,將scanf(“%s”,&str)中的&去掉。

第三條:在有返回值的函數中,控制流程到達函數尾,這個警告的意思是函數聲明存在返回值但是並未返回,將reverse函數返回聲明為void,並且為main函數最後面添加return 0語句

(在linux下,main函數聲明為void會產生警告如下圖:)

技術分享

所有警告處理完以後,結果截圖如下圖所示:

技術分享

3.4.運行程序

$./reverse

技術分享

此時發現輸入的abcdefg,但是最終結果是aecdcba,結果是與預期結果gfedcba完全不同的。

4.按照以下過程調試並修正reverse.c,請參考過程截圖。

4.1. 編譯時加入調試信息

$gcc -g reverse.c -o reverse1

技術分享

4.2. 啟用GDB調試

技術分享

使用file 命令,裝入想要調試的可執行程序 reverse1;

技術分享

4.3. 鍵入list,查看源代碼並根據行號/函數名設置斷點

技術分享

斷點設置總體如下:

技術分享

接下來是運行:

技術分享

4.4. 觀察變量值,並作分析,推測錯誤

技術分享

分析如下:

圖中所標示的1,2,3分別表示經過斷點以後,輸入的字符串變化情況;

在第一步中,由於只是執行了c=*str+i,也就是說字符串不會發生變化,對比圖片所給出的變化情況,可以得知這個結果是正確的,也就是說第一步不存在錯誤;

在第二步中,執行代碼*(str+1)=*str+len-i-1,按照正常情況,字符串第一個字符應該被最後一個字符所替代,但結果卻是第二個字符被最後一個字符替代,所以很可能在這裏出錯了;

在第三步中,執行c=*str+i;也即是最後一個字符串被變量c所指代的字符替代,由第一步,可以知道,最後一個結果應該是被第一個字符所替代,對比圖片的結果,結果是正確的,也即是說該代碼不存在錯誤;

4.5. 修正程序並運行

在上述步驟的分析中,有如下修改方案:將第二步中的*(str+1)=*str+len-i-1修改為*(str+i)=*str+len-i-1

修改完成後嘗試運行reverse.c:

技術分享

結果是:結果更加離譜-。-

沒辦法,接下來重新進入gdb調試:

4.6. 觀察變量值,並作分析,推測錯誤

調試結果如下:

技術分享

分析過程同4.4,這裏直接給出最終分析結果:1-4步結果是符合實際的,而在第5步中,hbcdefga本應該是轉化為hgcdefga,也即是倒數第二個賦值給第二個,但是結果卻是hncdefga,這個n來的有點莫名其妙,但在仔細分析代碼後發現,代碼竟然是*(str+i)=*str+len-i-1,omg!後面的表達式竟然沒加大括號!-.-

如果不加大括號後面的表達式的意思是*str=‘h’,然後len=8,i=1,就有‘h’+8-1-1----->‘n’,轉化為字符‘n’;

恩,知道哪裏錯了以後,先在reverse.c相應位置加上大括號(截圖如下)

技術分享

然後再來運行一次。

4.7. 修正程序並運行

技術分享

顯然,實驗結果是正確無誤的。

至此,“計算機系統概論”這門課的第一次實驗算是總體完成了,另外,在學習過程中難免會有疏漏,如果發現了本文中的某些錯誤,歡迎提出指正ヽ(???)?(???)?

技術分享

實驗一:實驗環境配置與使用