順序發展。
GNU C編譯器
用gdb調試GCC應用程序
您還可以看到隨Linux分發的其他有用的C編程工具。這些工具包括源代碼美容。
漂亮的打印程序,額外的調試工具,自動功能原型生成工具。
(自動功能原型)。
GNU C編譯器
隨Slackware Linux發布的GNU C編譯器(GCC)是壹個全功能的ANSI C和。
編譯器。如果您熟悉其他操作系統或硬件平臺上的C編譯器,您將能夠很快。
成功把握GCC。
使用GCC
通常後跟壹些選項和文件名來使用GCC編譯器。gcc命令的基本用法如下:
gcc[選項][文件名]
命令行選項指定的操作將在命令行上的每個給定文件上執行。下壹節將描述它。
您最常使用的壹些選項。
GCC選項
GCC有超過100種編譯選項可用。這些選項中的許多可能永遠不會被使用。
但是壹些主要選項會經常使用。許多GCC選項包含多個字符。所以妳
您必須為每個選項指定壹個單獨的連字符,像大多數Linux命令壹樣,您不能在
壹個連字符後跟壹組選項。例如,以下兩個命令是不同的:
gcc -p -g測試
gcc -pg測試
第壹個命令告訴GCC在編譯test.c和
並將調試信息添加到可執行文件中。第二個命令只告訴GCC為gprof命令構建它。
解析信息。
當妳編譯壹個沒有任何選項的程序時,GCC會創建壹個名為。
. out可執行文件。例如,以下命令將在當前目錄中生成壹個名為a.out的文檔。
件數:
gcc測試
您可以使用-o編譯選項來指定要生成的可執行文件的文件名,而不是. out
例如,要將名為count.c的C程序編譯成名為count的可執行文件,您將輸入
以下命令:
gcc -o計數計數
-
-
註意:使用-o選項時,-o後面必須跟壹個文件名。
-
-
GCC還有壹個編譯選項,指定編譯器將處理多少內容。c選項告訴GCC只編譯源代碼。
翻譯成目標代碼,跳過組裝和連接的步驟。此選項使用非常頻繁,因為它進行編譯。
多個C程序更快更容易管理。默認情況下,GCC建立了壹個目標代碼文件。
。o擴展。
S編譯選項告訴GCC停止編譯。GCC制作後生成匯編語言文件為C代碼。
生成的匯編語言文件的默認擴展名是。s. -E選項指示編譯器只預編譯輸入文件。
正在處理。使用此選項時,預處理器的輸出被發送到標準輸出,而不是存儲在文件中。
優化選項
當妳用GCC編譯C代碼時,它會盡量在最少的時間內完成編譯,並使編譯後的
代碼很容易調試。易於調試意味著編譯後的代碼與源代碼具有相同的執行順序。編譯後,
的代碼未優化。有很多選項可以告訴GCC花更多的編譯時間,犧牲易用性。
在調試的基礎上,生成更小更快的可執行文件。這些選項中最典型的是-O和-O2。
項目。
O選項告訴GCC對源代碼進行基本的優化。這些優化將在大多數情況下使流程。
序列執行更快。-O2選項告訴GCC生成盡可能小和盡可能快的代碼。-O2選項將
使編譯比使用-O時慢,但通常生成的代碼會執行得更快。
除了-O和-O2優化選項之外,還有壹些用於生成更快代碼的低級選項。這些
選項非常特殊,只有當您完全理解這些選項會對編譯後的代碼產生什麽影響時才是最好的。
用什麽樣的效果。有關這些選項的詳細描述,請參考GCC命令行指南頁面。
在上鍵入man gcc。
調試和分析選項
GCC支持幾個調試和分析選項。在這些選項中,-g和-pg是最常用的。
選項。
g選項告訴GCC生成調試信息,GNU調試器可以使用這些信息來調試您的程序。
GCC提供了許多其他c編譯器沒有的特性。在GCC中,可以讓-g和-O(
這非常有用,因為妳可以盡可能接近最終產品。
調試您的代碼。當妳同時使用這兩個選項時,妳必須知道妳寫的壹些代碼已經很優秀了。
是GCC改的。關於調試C程序的更多信息,請參閱下壹節“用gdb調試C”
程序”。
-pg選項告訴GCC向您的程序添加額外的代碼,當它被執行時,它將生成gprof。
解析信息以顯示程序的時間消耗。有關gprof的更多信息,請參考“gprof”I。
節日。
用gdb調試GCC程序
Linux包括壹個名為gdb的GNU調試器。gdb是壹個調試C和。
壹個強大的C++程序調試器。它使妳能夠觀察程序的內部結構和程序運行時內存的使用情況。
情況。以下是廣發銀行提供的部分功能:
它使您能夠監控程序中變量的值。
它使您能夠設置斷點來阻止程序在指定的代碼行上執行。
它使您能夠逐行執行代碼。
在命令行中鍵入gdb,然後按Enter運行gdb。如果壹切正常,
Gdb將被啟動,您將在屏幕上看到類似的內容:
GDB是自由軟件,歡迎妳分發它的拷貝
在壹定條件下;鍵入“顯示復制”以查看條件。
GDB絕對沒有保修;鍵入“顯示保修”
細節。
GDB 4.14(i486-slak ware-Linux),版權1995自由軟件基金會
公司。
(廣發銀行)
當您啟動gdb時,您可以在命令行上指定許多選項。您也可以使用以下方法。
要運行gdb:
廣發銀行& ltfname & gt
這樣運行gdb時,可以直接指定要調試的程序。這會告訴gdb安裝它。
輸入名為fname的可執行文件。妳也可以使用gdb來檢查壹個由非正常終止引起的程序。
核心文件,或者連接到正在運行的程序。可以參考廣發指南頁面或者生活中。
在該行中鍵入gdb -h以獲得這些選項的簡單描述列表。
編譯用於調試的代碼。
為了讓gdb正常工作,妳必須讓妳的程序在編譯時包含調試信息。
包含程序中每個變量的類型、可執行文件中的地址映射以及源代碼的行號。
Gdb使用這些信息將源代碼和機器碼聯系起來。
在編譯時使用-g選項打開調試選項。
Gdb基本命令
Gdb支持許多命令,使您能夠實現不同的功能。這些命令從簡單文件加載到。
允許您檢查被調用堆棧內容的復雜命令。表27.1列出了使用gdb調試時將使用的命令。
壹些命令。關於廣發銀行的詳細使用方法,請參考廣發銀行的指南頁面。
表27.1。基本的gdb命令。
生活秩序的描述
File加載要調試的可執行文件。
Kill終止正在調試的程序。
List列出了生成執行文件的部分源代碼。
接下來執行壹行源代碼,而不進入函數。
Step執行壹行源代碼,進入函數。
Run執行當前調試的程序。
退出終止gdb
“監視”使您能夠在變量發生變化時監視變量的值。
Break在代碼中設置壹個斷點,當程序在這裏執行時,它將掛起程序。
Make使您能夠在不退出gdb的情況下重新生成可執行文件。
Shell使您能夠在不離開gdb的情況下執行UNIX shell命令。
Gdb支持許多與UNIX shell程序相同的命令編輯特性。您可以像在bash或
像在tcsh那樣按Tab鍵,讓gdb幫妳完成壹個獨特的命令。如果不是唯壹的,廣發銀行會
列出所有匹配的命令。您也可以使用光標鍵上下滾動歷史命令。
廣發銀行應用實例
本節用壹個例子來壹步步教妳用gdb調試壹個程序。調試的程序相當簡單。
但它展示了gdb的典型應用。
下面列出了要調試的程序。這個程序叫做問候,它展示了壹個簡單的
問候,然後倒序列出。
# include & ltstdio.h & gt
主()
{
char my_string[] = "妳好";
my_print(我的_ string);
my _ print 2(my _ string);
}
void my_print (char *string)
{
printf("字符串為%s\n ",字符串);
}
void my_print2 (char *string)
{
char * string2
int size,I;
size = strlen(字符串);
string 2 =(char *)malloc(size+1);
for(I = 0;我& lt尺寸;i++)
string 2[size-I]= string[I];
string2[size+1] = `\0 '
printf("向後打印的字符串是%s\n ",string 2);
}
使用以下命令編譯它:
測試測試
執行該程序時,將顯示以下結果:
弦樂是妳好
向後打印的字符串是
輸出的第壹行是正確的,但是第二行打印的內容不是我們預期的。我們所期待的
設想的產出應該是:
向後打印的字符串是ereht olleh
由於某種原因,我的_print2函數無法正常工作。我們用gdb看看問題出在哪裏。
它在哪裏?首先鍵入以下命令:
廣發問候
-
-
註意:編譯問候語程序時,記得打開調試選項。
-
-
如果您在輸入命令時忘記將想要調試的程序作為參數傳遞給gdb,您可以使用。
在gdb提示符下使用file命令來加載它:
(gdb)文件問候
這個命令將加載greeting可執行文件,就像您在gdb命令行上加載它壹樣。
此時可以使用gdb的run命令運行greeting。在廣發行運行的時候。
結果將是這樣的:
(廣東發展銀行)運行
啟動程序:/root/greeting
弦樂是妳好
向後打印的字符串是
程序退出,代碼為041
這個輸出和在gdb外運行是壹樣的。問題是,為什麽反印不行?
為了找出癥結,我們可以在my_print2函數的for語句後設置壹個斷點,用
正文的方法是在gdb提示符下鍵入list命令三次,列出源代碼:
(gdb)列表
(gdb)列表
(gdb)列表
提示:在gdb提示符下按Enter鍵重復最後壹個命令。
-
第壹次鍵入list命令的輸出如下:
1 # include & lt;stdio.h & gt
2
3主()
4 {
5 char my_string[] =“妳好”;
六
7 my_print(我的_ string);
8 my _ print 2(my _ string);
9 }
10
如果您按Enter鍵,gdb將再次執行list命令並給出以下輸出:
11 my _ print(char * string)
12 {
13 printf("字符串為%s\n ",字符串);
14 }
15
16 my_print2 (char *string)
17 {
18 char * string 2;
19 int size,I;
20再次按回車鍵,列出剩余的問候語程序:
21 size = strlen(string);
22 string 2 =(char *)malloc(size+1);
23 for(I = 0;我& lt尺寸;i++)
24 string 2[size-I]= string[I];
25 string2[size+1] = `\0 '
26 printf("向後打印的字符串是%s\n ",string 2);
27 }
根據列出的源程序,可以看到設置斷點的地方是在gdb命令提示符下的第24行。
在運算符下鍵入以下命令來設置斷點:
(gdb)中斷24
廣發銀行將做出如下回應:
0x139處的斷點1:文件greeting.c,第24行
(廣發銀行)
現在再次鍵入run命令,這將產生以下輸出:
啟動程序:/root/greeting
弦樂是妳好
greeting.c處的斷點1,my _ print 2(string = 0x bfffdc 4“hello there”)
:24
24 string2[size-i]=string[i]
可以看到錯誤是通過設置壹個觀察點來觀察string2[size-i]變量的值。
如何生成,通過鍵入:
(gdb)表鏈2[size - i]
廣發銀行將做出如下回應:
觀察點2:字符串2[size - i]
現在,您可以使用下壹個命令來逐步執行for循環:
(廣發)下壹個
第壹次循環之後,gdb告訴我們string2[size-i]的值是‘h’。用的是gdb。
以下顯示將告訴您這些信息:
觀察點2,字符串2[大小- i]
舊值= 0 `\000 '
新值= 104 ' h '
my_print2(string = 0xbfffdc4“妳好”)at greeting.c:23
23 for(I = 0;我& lt尺寸;i++)
該值是預期值。幾個後續循環的結果都是正確的。當i=10時,表達式
string2[size-i]的值等於‘e ’, size-I的值等於1,最後壹個字符已被
它被復制到壹個新的字符串中。
如果繼續循環,您將看到沒有為string2[0]賦值,並且
它是新字符串的第壹個字符,因為malloc函數在分配內存時將它們初始化為null。
(空)字符。所以string2的第壹個字符是空字符。這解釋了為什麽它正在打印。
string2時沒有輸出。
既然我們已經發現了問題所在,就很容易糾正這個錯誤。妳必須把它寫在代碼裏。
string2的第壹個字符的偏移量改為size-1,而不是size。這是因為
string2的大小是12,但是起始偏移量是0,字符串中的字符從偏移量0到偏移量。
10,偏移量11為空字符保留。
為了讓代碼正常工作,有很多方法可以修改。壹種是設置另壹個比字符串實際大小小1的。
這是該解決方案的代碼:
# include & ltstdio.h & gt
主()
{
char my_string[] = "妳好";
my_print(我的_ string);
my _ print 2(my _ string);
}
my_print (char *string)
{
printf("字符串為%s\n ",字符串);
}
my_print2 (char *string)
{
char * string2
int size,size2,I;
size = strlen(字符串);
size 2 = size-1;
string 2 =(char *)malloc(size+1);
for(I = 0;我& lt尺寸;i++)
string 2[size 2-I]= string[I];
string2[size] = `\0 '
printf("向後打印的字符串是%s\n ",string 2);
}
另壹個c編程工具
Slackware Linux發行版還包括壹些我們還沒有提到的C開發工具。這部分
將介紹這些工具及其典型用法。
xxgdb
Xxgdb是基於X Window系統的gdb圖形界面。xxgdb包括命令行。
gdb版本的所有功能。xxgdb使您能夠通過按下按鈕來執行常用命令。出發。
點也以圖形方式顯示。
您可以通過在Xterm窗口中鍵入以下命令來運行它:
xxgdb
您可以在gdb用任何有效的命令行選項初始化XXgdb。另外,xxgdb也有壹個
表27.2列出了壹些獨特的命令行選項。
表27.2。xxgdb命令行選項。
可選項目的描述
Db_name指定所用調試器的名稱。默認為gdb。
Db_prompt指定調試器提示,默認為gdb。
Gdbinit指定初始化gdb的命令文件的文件名,默認為。gdbinit。
Nx告訴xxgdb不要執行。gdbinit文件。
Bigicon使用大圖標。
打電話
您可以在sunsite.unc.edu FTP站點使用以下路徑:
/pub/Linux/devel/lang/c/calls . tar . z
為了獲得調用,壹些舊版本的Linux CD-ROM發行版也附帶了它們。因為它是
壹個有用的工具,我們也在這裏介紹壹下。如果妳覺得有用,就從BBS,FTP,
或者在另壹張CD-ROM上獲得壹份副本。調用GCC的預處理器來處理給定的源程序。
序列文件,然後在這些文件中輸出函數調用樹形圖。
-
註意:在您的系統上安裝調用,以超級用戶身份登錄並執行以下步驟:1。解決方案。
按下並解壓縮文件。2.CD進入後創建的子目錄調用untar。3.將其命名
將調用文件移動到/usr/bin目錄。4.將名為calls.1的文件移動到目錄中。
/usr/man/man1。5.刪除/tmp/calls目錄。這些步驟將把調用程序及其引用。
您的系統上安裝了南頁。
-
當calls輸出調用跟蹤結果時,它會在函數後面的括號中給出函數的文本。
文件名:
主[測試. c]
如果函數不在給calls的文件中,calls就不知道被調用的函數來自哪裏。
其中,僅顯示函數的名稱:
打印函數
Calls不輸出遞歸和靜態函數。遞歸函數如下所示:
事實& lt& lt& ltfactorial.c & gt中的遞歸& gt& gt
靜態函數顯示如下:
total[在calculate.c中靜態]
例如,假設以下程序由調用處理:
# include & ltstdio.h & gt
主()
{
char my_string[] = "妳好";
my_print(我的_ string);
my _ print 2(my _ string);
}
my_print (char *string)
{
printf("字符串為%s\n ",字符串);
}
my_print2 (char *string)
{
char * string2
int size,size2,I;
size = strlen(字符串);
size 2 = size-1;
string 2 =(char *)malloc(size+1);
for(I = 0;我& lt尺寸;i++)
string 2[size 2-I]= string[I];
string2[size] = `\0 '
printf("向後打印的字符串是%s\n ",string 2);
}
將產生以下輸出:
1主[test.c]
2 my_print [test.c]
3打印f
4 my_print2 [test.c]
5 strlen
6 malloc
7印刷f
Calls有許多命令行選項來設置不同的輸出格式。有關這些選項的更多信息,請參考。
來電指南頁。方法是在命令行上鍵入calls -h。
cproto
Cproto讀取C源程序文件,自動為每個函數生成壹個原型語句。使用cproto,您可以
寫程序的時候,定義函數原型會節省妳很多時間。
如果讓cproto處理下面的代碼:
# include & ltstdio.h & gt
主()
{
char my_string[] = "妳好";
my_print(我的_ string);
my _ print 2(my _ string);
}
my_print (char *string)
{
printf("字符串為%s\n ",* string);
}
my_print2 (char *string)
{
char * string2
int size,size2,I;
size = strlen(字符串);
size 2 = size-1;
string 2 =(char *)malloc(size+1);
for(I = 0;我& lt尺寸;i++)
string 2[size 2-I]= string[I];
string2[size] = `\0 '
printf("向後打印的字符串是%s\n ",string 2);
}
您將獲得以下輸出:
/* test.c */
int main(void);
int my _ print(char * string);
int my _ print 2(char * string);
這個輸出可以被重定向到壹個定義函數原型的包含文件。
縮進
縮進工具是Linux中包含的另壹個編程工具。這個工具簡單地說。
為妳的代碼創建壹個漂亮的縮進格式。縮進也有許多選項來指定如何格式化妳。
有關這些選項的更多信息,請參見indent的指南頁,並在命令行中鍵入indent -h。
以下示例是縮進的默認輸出:
縮進前運行c代碼:
# include & ltstdio.h & gt
main () {
char my_string[] = "妳好";
my_print(我的_ string);
my _ print 2(my _ string);}
my_print (char *string)
{
printf("字符串為%s\n ",* string);
}
my_print2 (char *string) {
char * string2
int size,size2,I;
size = strlen(字符串);
size 2 = size-1;
string 2 =(char *)malloc(size+1);
for(I = 0;我& lt尺寸;i++)
string 2[size 2-I]= string[I];
string2[size] = `\0 '
printf("向後打印的字符串是%s\n ",string 2);
}
運行縮進後的c代碼:
# include & ltstdio.h & gt
主()
{
char my_string[] = "妳好";
my_print(我的_ string);
my _ print 2(my _ string);
}
my_print (char *string)
{
printf("字符串為%s\n ",* string);
}
my_print2 (char *string)
{
char * string2
int size,size2,I;
size = strlen(字符串);
size 2 = size-1;
string 2 =(char *)malloc(size+1);
for(I = 0;我& lt尺寸;i++)
string 2[size 2-I]= string[I];
string2[size] = `\0 '
printf("向後打印的字符串是%s\n ",string 2);
}
縮進並沒有改變代碼的實質,只是改變了代碼的外觀,使其可讀性更好。
這總是壹件好事。
gprof
Gprof是安裝在Linux系統的/usr/bin目錄中的壹個程序。它使您能夠
分析妳的程序,以了解程序的哪壹部分執行時間最長。
Gprof會告訴妳程序中每個函數被調用了多少次,每個函數執行需要多少時間。
如果您想提高程序的性能,這些信息非常有用。
為了在程序中使用gprof,您必須在編譯程序時添加-pg選項。這將使
該程序每次執行時都會生成壹個名為gmon.out的文件。gprof使用這個文件來生成分析信息。
在運行您的程序並生成gmon.out文件之後,您可以使用下面的命令來獲取分析信。
興趣:
gprof & ltprogram _ name & gt
參數program_name是生成gmon.out文件的程序的名稱。
-
提示:gprof會生成很多分析數據,所以如果想檢查這些數據,最好重定向輸出。
放到壹個文件裏。
-
F2c和p2c
F2c和p2c是兩個源代碼轉換程序。f2c將FORTRAN代碼轉換成C代碼,
P2c將Pascal代碼轉換成C代碼。當您安裝GCC時,這兩個程序都將被安裝。
。
如果妳有壹些用FORTRAN或Pascal寫的代碼需要用C、f2c和p2c重寫。
對妳很有用。這兩個程序生成的C代碼可以直接用GCC編譯,不需要修改。
如果要轉換的FORTRAN或Pascal程序比較小,可以直接用f2c或p2c。
不需要添加任何選項。如果要轉換的程序很大,並且包含許多文件,您可能需要使用它。
壹些命令行選項。
在FORTRAN程序上使用f2c,輸入以下命令:
f2c my_fortranprog.f
-
註意:f2c要求轉換後的程序的擴展名為。f或a.f .
-
要用C程序替換Pascal程序,請輸入以下命令:
p2c my_pascalprogram.pas
這兩個程序生成的C源代碼的文件名與原文件名相同,只是擴展名為。f.
或者。pas變成了。c.
=================================================================
如果是做工程的,還是要懂make。建議妳學習make。
=================================================================