實驗一:實驗環境配置與使用
一、實驗目標:
熟悉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. 修正程序並運行
顯然,實驗結果是正確無誤的。
至此,“計算機系統概論”這門課的第一次實驗算是總體完成了,另外,在學習過程中難免會有疏漏,如果發現了本文中的某些錯誤,歡迎提出指正ヽ(???)?(???)?
實驗一:實驗環境配置與使用