火龙果·整理 大子大⊙uml.org.cn 关于gcc命令的使用语法如下: gcc [options][filenames] 命令行[options](选项)指定的操作将在命令行上每个给出的文件上执行,GCC有超 过100个的编译选项可用,这些选项中的许多你可能永远都不会用到,但一些主要的选项将 会频繁用到。很多的GCC选项包括一个以上的字符。因此你必须为每个选项指定各自的 连字符,并且就象大多数Liux命令一样你不能在一个单独的连字符后跟一组选项,例如, 下面的两个命令是不同的: #gcc-p-g test.c #gcc-pg test.c 第一条命令告诉GCC编译test.c时为prof命令建立剖析(profile)信息并且把调试信 息加入到可执行的文件里。而第二条命令只告诉GCC为gprof命令建立剖析信息。所以 在使用多个选项时一定要注意。 当你不用任何选项编译一个程序时,GCC将会建立(假定编译成功)一个名为a.out的 可执行文件。例如,下面的命令将在当前目录下产生一个叫aout的文件: #gcc test.c 你可以用-o编译选项来为将产生的可执行文件指定一个文件名来代替a.out。例如, 将一个叫test.c的C程序编译为名叫test的可执行文件,你将输入下面的命令: gcc-o test test.c 注意,当你使用-0选项时,-0后面必须跟一个文件名。 GCC同样有指定编译器处理多少的编译选项,-C选项告诉GCC仅把源代码编译为目 标代码而跳过汇编和连接的步骤。这个选项使用的非常频繁因为它使得编译多个C程序时 速度更快并且更易于管理。缺省时GCC建立的目标代码文件有一个.0的扩展名。-S编 译选项告诉GCC在为C代码产生了汇编语言文件后停止编译。GCC产生的汇编语言文 件的缺省扩展名是5。E选项指示编译器仅对输入文件进行预处理。当这个选项被使用 时,预处理器的输出被送到标准输出而不是储存在文件里。 当你用GCC编译C代码时,它会试着用最少的时间完成编译并且使编译后的代码易 于调试。易于调试意味着编译后的代码与源代码有同样的执行次序,编译后的代码没有经过 优化。有很多选项可用于告诉GCC在耗费更多编译时间和牺牲易调试性的基础上产生更 小更快的可执行文件。这些选项中最典型的是-O和-O2选项。-0选项告诉GC℃对源代 码进行基本优化。这些优化在大多数情况下都会使程序执行的更快。-O2选项告诉GCC产 生尽可能小和尽可能快的代码。-O2选项将使编译的速度比使用-0时慢。但通常产生的 代码执行速度会更快。如果想了解GCC的详细描述,请参考GCC的指南页,在命令行上 键入man gcc就可以看到所有GCC的选项说明。 1.4.2.2 GNU Make介绍 GNU Make工具是Linux下非常重要的一个开发工具,当你编译只有几个源文件的程序 时也许觉得Mak®工具并没多大意义,但是当你开发一个庞大的软件系统(比如成千上万个 源文件)时,Make工具就变得必不可少了。作为一个Linux开发人员,熟悉make工具的 使用以及编写自己的Makefile是必需的。在Linux环境下使用GNU的make工具能够比较 容易的构建一个属于你自己的工程,整个工程的编译只需要一个命令就可以完成编译、连接 以至于最后的执行。在ake命令后不仅可以出现宏定义,还可以跟其他命令行参数,这些 参数指定了需要编译的目标文件。其标准形式为: target1 [target2...]:[:][dependentl ...][;commands][#
关于 gcc 命令的使用语法如下: # gcc [options] [filenames] 命令行[options](选项)指定的操作将在命令行上每个给出的文件上执行,GCC 有超 过 100 个的编译选项可用,这些选项中的许多你可能永远都不会用到, 但一些主要的选项将 会频繁用到。很多的 GCC 选项包括一个以上的字符。因此你必须为每个选项指定各自的 连字符,并且就象大多数 Linux 命令一样你不能在一个单独的连字符后跟一组选项, 例如, 下面的两个命令是不同的: # gcc -p -g test.c # gcc -pg test.c 第一条命令告诉 GCC 编译 test.c 时为 prof 命令建立剖析(profile)信息并且把调试信 息加入到可执行的文件里。而第二条命令只告诉 GCC 为 gprof 命令建立剖析信息。所以 在使用多个选项时一定要注意。 当你不用任何选项编译一个程序时, GCC 将会建立(假定编译成功)一个名为 a.out 的 可执行文件。例如,下面的命令将在当前目录下产生一个叫 a.out 的文件: # gcc test.c 你可以用 -o 编译选项来为将产生的可执行文件指定一个文件名来代替 a.out。 例如, 将一个叫 test.c 的 C 程序编译为名叫 test 的可执行文件,你将输入下面的命令: # gcc –o test test.c 注意,当你使用 -o 选项时, -o 后面必须跟一个文件名。 GCC 同样有指定编译器处理多少的编译选项,-c 选项告诉 GCC 仅把源代码编译为目 标代码而跳过汇编和连接的步骤。这个选项使用的非常频繁因为它使得编译多个 C 程序时 速度更快并且更易于管理。缺省时 GCC 建立的目标代码文件有一个 .o 的扩展名。-S 编 译选项告诉 GCC 在为 C 代码产生了汇编语言文件后停止编译。GCC 产生的汇编语言文 件的缺省扩展名是 .s。 -E 选项指示编译器仅对输入文件进行预处理。当这个选项被使用 时,预处理器的输出被送到标准输出而不是储存在文件里。 当你用 GCC 编译 C 代码时,它会试着用最少的时间完成编译并且使编译后的代码易 于调试。易于调试意味着编译后的代码与源代码有同样的执行次序,编译后的代码没有经过 优化。有很多选项可用于告诉 GCC 在耗费更多编译时间和牺牲易调试性的基础上产生更 小更快的可执行文件。这些选项中最典型的是-O 和 -O2 选项。-O 选项告诉 GCC 对源代 码进行基本优化。这些优化在大多数情况下都会使程序执行的更快。-O2 选项告诉 GCC 产 生尽可能小和尽可能快的代码。-O2 选项将使编译的速度比使用 -O 时慢。但通常产生的 代码执行速度会更快。如果想了解 GCC 的详细描述, 请参考 GCC 的指南页, 在命令行上 键入 man gcc 就可以看到所有 GCC 的选项说明。 1.4.2.2 GNU Make 介绍 GNU Make 工具是 Linux 下非常重要的一个开发工具,当你编译只有几个源文件的程序 时也许觉得 Make 工具并没多大意义,但是当你开发一个庞大的软件系统(比如成千上万个 源文件)时,Make 工具就变得必不可少了。作为一个 Linux 开发人员,熟悉 make 工具的 使用以及编写自己的 Makefile 是必需的。在 Linux 环境下使用 GNU 的 make 工具能够比较 容易的构建一个属于你自己的工程,整个工程的编译只需要一个命令就可以完成编译、连接 以至于最后的执行。在 make 命令后不仅可以出现宏定义,还可以跟其他命令行参数,这些 参数指定了需要编译的目标文件。其标准形式为: target1 [target2 …]:[:][dependent1 …][;commands][#…]
火龙果·整理 子大⊙uml.org.cn [(tab)commands][#...] 方括号中间的部分表示可选项。Targets和dependents当中可以包含字符、数字、句点和"" 符号。除了引用,commands中不能含有"#",因为"#"在这里代表注释行的开始,也不允许 换行。 在通常的情况下命令行参数中只含有一个":",此时command序列通常和makefile文件 中某些定义文件间依赖关系的描述行有关。如果与目标相关连的那些描述行指定了相关的 command序列,那么就执行这些相关的command命令,即使在分号和(tab)后面的command 字段甚至有可能是NULL。如果那些与目标相关连的行没有指定command,.那么将调用系 统默认的目标文件生成规则。 如果命令行参数中含有两个冒号":",则此时的command序列也许会和makefile中所有 描述文件依赖关系的行有关。此时将执行那些与目标相关连的描述行所指向的相关命令。同 时还将执行build-in规则。 如果在执行command命令时返回了一个非"O"的出错信号,例如makefile文件中出现了 错误的目标文件名或者出现了以连字符打头的命令字符串,make操作一般会就此终止,但 如果make后带有"-i"参数,则make将忽略此类出错信号。 Make命本身可带有四种参数:标志、宏定义、描述文件名和目标文件名。其标准形式 为: make [flags][macro definitions][targets] Unix/Linux系统下标志位flags选项及其含义为: -ffle指定file文件为描述文件,如果file参数为"."符,那么描述文件指向标准输入。 如果没有"-f"参数,则系统将默认当前目录下名为makefile或者名为Makefile的文件为描述 文件。在Linux中,GNU make工具在当前工作目录中按照GNUmakefile、makefile、Makefile 的顺序搜索makefile文件。 i忽略命令执行返回的出错信息。 -S沉默模式,在执行之前不输出相应的命令行信息。 -r禁止使用build-in规则。 n非执行模式,输出所有执行命令,但并不执行。 t更新目标文件。 -q make操作将根据目标文件是否己经更新返回"0"或非"0"的状态信息。 P输出所有宏定义和目标文件描述。 -d Debug模式,输出有关文件的调试信息。 Linux下make标志位的常用选项与Unix系统中稍有不同,下面我们只列出了不同部分: -cdir在读取makefile之前改变到指定的目录dir。 -Idir当包含其他makefile文件时,利用该选项指定搜索目录。 -h help文挡,显示所有的make选项。 -w在处理makefile之前和之后,都显示工作目录。 通过命令行参数中的target,,可指定make要编译的目标,并且允许同时定义编译多个 目标,操作时按照从左向右的顺序依次编译target选项中指定的目标文件。如果命令行中没 有指定目标,则系统默认target指向描述文件中第一个目标文件。为了能快速的对make和 Makefile有个大体了解,这里给出一个最简单的Makefile实例。假设源文件有四个:main.c, filel.c,fle2.c,filel.h和fle2.h。Makefile文件编写如下: 1#最简单的Makefile 2 CC=gcc 3 exec=test.exe
[(tab) commands][#…] 方括号中间的部分表示可选项。Targets 和 dependents 当中可以包含字符、数字、句点和"/" 符号。除了引用,commands 中不能含有"#",因为"#"在这里代表注释行的开始,也不允许 换行。 在通常的情况下命令行参数中只含有一个":",此时 command 序列通常和 makefile 文件 中某些定义文件间依赖关系的描述行有关。如果与目标相关连的那些描述行指定了相关的 command 序列,那么就执行这些相关的 command 命令,即使在分号和(tab)后面的 command 字段甚至有可能是 NULL。如果那些与目标相关连的行没有指定 command,那么将调用系 统默认的目标文件生成规则。 如果命令行参数中含有两个冒号"::",则此时的 command 序列也许会和 makefile 中所有 描述文件依赖关系的行有关。此时将执行那些与目标相关连的描述行所指向的相关命令。同 时还将执行 build-in 规则。 如果在执行 command 命令时返回了一个非"0"的出错信号,例如 makefile 文件中出现了 错误的目标文件名或者出现了以连字符打头的命令字符串,make 操作一般会就此终止,但 如果 make 后带有"-i"参数,则 make 将忽略此类出错信号。 Make 命本身可带有四种参数:标志、宏定义、描述文件名和目标文件名。其标准形式 为: make [flags] [macro definitions] [targets] Unix/Linux 系统下标志位 flags 选项及其含义为: -f file 指定 file 文件为描述文件,如果 file 参数为"-"符,那么描述文件指向标准输入。 如果没有"-f"参数,则系统将默认当前目录下名为 makefile 或者名为 Makefile 的文件为描述 文件。在 Linux 中,GNU make 工具在当前工作目录中按照 GNUmakefile、makefile、Makefile 的顺序搜索 makefile 文件。 -i 忽略命令执行返回的出错信息。 -s 沉默模式,在执行之前不输出相应的命令行信息。 -r 禁止使用 build-in 规则。 -n 非执行模式,输出所有执行命令,但并不执行。 -t 更新目标文件。 -q make 操作将根据目标文件是否已经更新返回"0"或非"0"的状态信息。 -p 输出所有宏定义和目标文件描述。 -d Debug 模式,输出有关文件的调试信息。 Linux 下 make 标志位的常用选项与 Unix 系统中稍有不同,下面我们只列出了不同部分: -c dir 在读取 makefile 之前改变到指定的目录 dir。 -I dir 当包含其他 makefile 文件时,利用该选项指定搜索目录。 -h help 文挡,显示所有的 make 选项。 -w 在处理 makefile 之前和之后,都显示工作目录。 通过命令行参数中的 target,可指定 make 要编译的目标,并且允许同时定义编译多个 目标,操作时按照从左向右的顺序依次编译 target 选项中指定的目标文件。如果命令行中没 有指定目标,则系统默认 target 指向描述文件中第一个目标文件。为了能快速的对 make 和 Makefile 有个大体了解,这里给出一个最简单的 Makefile 实例。假设源文件有四个:main.c, file1.c, file2.c, file1.h 和 file2.h。Makefile 文件编写如下: 1 # 最简单的 Makefile 2 CC=gcc 3 exec=test.exe
4 obj=main.o filel.o file2.o 5 $(exec):$(obj) 6 $(CC)-o $(exec)$(obj) $(objects):%.0:%.c 8 $(CC)-c$< 9 10 .PHONY:clean 11 clean: 12 -rm $(exec)$(obj) Makefile文件有几个非常有用的变量:分别是$@、$*、$?、$^、$<,其代表的意义 分别是: $@-完整的目标文件,包括扩展名 $*目标文件去掉后缀的部分 S ·所有的依赖文件 $<…比目标文件更新的依赖文件 $?-表示被修改的文件 在此解释一下上述的Makefile,这是一个非常简单的makefile,make从最上面开始。 其中#号用来注释行用得,所以第1行是注释行。第2-4行,用来定义变量,其中定义了编 译器为gcc:可执行文件为test.exe:目标文件有main.o,flel.o和file2.o。第5行,表示了 可执行文件依赖于目标文件,注意在引用变量前一定要加$符号,否则系统不能正确引用该 变量。第6行,该行是命令行,值得注意的是命令行前一定是以[Tb]键开始,否则系统不 能执行命令。该行等价于“gcc-o test..exe main.o filel.o file2.o”。第7行,表示目标文件依 赖于具体的源文件。第8行,意思是当有文件更新时执行编译。第10-12行,建立一个执行 make的清除选项,实现的功能是删除可执行文件和目标文件。 在Makefile建立完成后,在有Makefile文件的目录下通过命令行输入以下命令: #make 上述命令的作用就是执行源代码的编译,编译的顺序和逻辑由所编写的Makefile文件决定, 以上述的Makefile为例,执行后会生成一个文件名为test.exe的可执行性文件,然后输入以 下命令执行该文件: #/test 此外,可以在命令行输入以下命令来清除可执行文件test.exe,目标文件main.o,flel.o 和file2.o。 make clean 通过上面的例子可以对Make和Makefile有了感性的认识,在实际工作中makefile文件 会比较庞大,相对比较复杂,不过万变不离其宗,它的实现方式和目的都是一样,通过具体 实践应用读者一定会觉得Makefile的编写并不是什么难事。 1.4.2.3GDB介绍 Linux包含了一个叫GDB(GNU DeBugger)的GNU调试程序。GDB是一个用来调 试C和C+程序的强大调试器。它使你能在程序运行时观察程序的内部结构和内存的使 用情况。以下是GDB所提供的一些基本功能: >监视程序中变量的值 设置断点以使程序在指定的代码行上停止执行
4 obj=main.o file1.o file2.o 5 $(exec) : $(obj) 6 $(CC) -o $(exec) $(obj) 7 $(objects) : %.o : %.c 8 $(CC) -c $< 9 10 .PHONY: clean 11 clean: 12 -rm $(exec) $(obj) Makefile 文件有几个非常有用的变量:分别是 $@、$*、$?、$^、$< ,其代表的意义 分别是: $@ -- 完整的目标文件,包括扩展名 $* -- 目标文件去掉后缀的部分 $^ -- 所有的依赖文件 $< -- 比目标文件更新的依赖文件 $? -- 表示被修改的文件 在此解释一下上述的 Makefile,这是一个非常简单的 makefile ,make 从最上面开始。 其中#号用来注释行用得,所以第 1 行是注释行。第 2-4 行,用来定义变量,其中定义了编 译器为 gcc;可执行文件为 test.exe;目标文件有 main.o,file1.o 和 file2.o。第 5 行,表示了 可执行文件依赖于目标文件,注意在引用变量前一定要加$符号,否则系统不能正确引用该 变量。第 6 行,该行是命令行,值得注意的是命令行前一定是以[Tab]键开始,否则系统不 能执行命令。该行等价于“gcc –o test.exe main.o file1.o file2.o”。第 7 行,表示目标文件依 赖于具体的源文件。第 8 行,意思是当有文件更新时执行编译。第 10-12 行,建立一个执行 make 的清除选项,实现的功能是删除可执行文件和目标文件。 在 Makefile 建立完成后,在有 Makefile 文件的目录下通过命令行输入以下命令: # make 上述命令的作用就是执行源代码的编译,编译的顺序和逻辑由所编写的 Makefile 文件决定, 以上述的 Makefile 为例,执行后会生成一个文件名为 test.exe 的可执行性文件,然后输入以 下命令执行该文件: # ./test 此外,可以在命令行输入以下命令来清除可执行文件 test.exe,目标文件 main.o,file1.o 和 file2.o。 # make clean 通过上面的例子可以对 Make 和 Makefile 有了感性的认识,在实际工作中 makefile 文件 会比较庞大,相对比较复杂,不过万变不离其宗,它的实现方式和目的都是一样,通过具体 实践应用读者一定会觉得 Makefile 的编写并不是什么难事。 1.4.2.3 GDB 介绍 Linux 包含了一个叫 GDB(GNU DeBugger)的 GNU 调试程序。GDB 是一个用来调 试 C 和 C++ 程序的强大调试器。它使你能在程序运行时观察程序的内部结构和内存的使 用情况。以下是 GDB 所提供的一些基本功能: Ø 监视程序中变量的值 Ø 设置断点以使程序在指定的代码行上停止执行
>单步执行代码 在命令行上键入gdb并按回车键就可以运行GDB了,如果己经正常安装的话,GDB将 被启动并且将在屏幕上看到以下类似的内容: GNU gdb Red Hat Linux(5.3post-0.20021129.18rh) Copyright 2003 Free Software Foundation,Inc. GDB is free software,covered by the GNU General Public License,and you are welcome 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"i386-redhat-linux-gnu". (gdb) GDB支持很多的命令使你能实现不同的功能。这些命令从简单的文件装入到允许你检 查所调用的堆栈内容的复杂命令,如表1.1列出了b调试时会用到的一些命令。想了解 GDB的详细使用请参考GDB的指南页。 表1.1GDB常用命令描述 命令 命令描述 break 在代码里设置断点,这将使程序执行到这里时被挂起 file 装入想要调试的可执行文件 kill 终止正在调试的程序 list 列出产生执行文件的源代码的一部分 make 使你在不退出gdb时就可以重新产生可执行文件 next 执行一行源代码但不进入函数内部 print 显示表达式的值 quit 终止gdb run 执行当前被调试的程序 shell 使你能不离开gdb就执行shell命令 step 执行一行源代码而且进入函数内部 watch 监视一个变量的值而不管它何时被改变 接下来举一个简单的GDB使用实例,使读者能够初步了解在Liux系统下应用程序的 调试过程。 首先建立一个被调试的程序名叫test.c,文件内容如下: #include <stdio.h> int main() { char str1[]="Hello,world"; char str2[11]=""; int i=0; while(str1[il!=10') str2[i]=strl[i]; i计+; }
Ø 单步执行代码 在命令行上键入 gdb 并按回车键就可以运行 GDB 了, 如果已经正常安装的话, GDB 将 被启动并且将在屏幕上看到以下类似的内容: GNU gdb Red Hat Linux (5.3post-0.20021129.18rh) Copyright 2003 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome 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 "i386-redhat-linux-gnu". (gdb) GDB 支持很多的命令使你能实现不同的功能。这些命令从简单的文件装入到允许你检 查所调用的堆栈内容的复杂命令, 如表 1.1 列出了 gdb 调试时会用到的一些命令。想了解 GDB 的详细使用请参考 GDB 的指南页。 表 1.1 GDB 常用命令描述 命令 命令描述 break 在代码里设置断点, 这将使程序执行到这里时被挂起 file 装入想要调试的可执行文件 kill 终止正在调试的程序 list 列出产生执行文件的源代码的一部分 make 使你在不退出 gdb 时就可以重新产生可执行文件 next 执行一行源代码但不进入函数内部 print 显示表达式的值 quit 终止 gdb run 执行当前被调试的程序 shell 使你能不离开 gdb 就执行 shell 命令 step 执行一行源代码而且进入函数内部 watch 监视一个变量的值而不管它何时被改变 接下来举一个简单的 GDB 使用实例,使读者能够初步了解在 Linux 系统下应用程序的 调试过程。 首先建立一个被调试的程序名叫 test.c,文件内容如下: #include <stdio.h> int main() { char str1[]="Hello,world"; char str2[11]=""; int i=0; while(str1[i]!='\0') { str2[i]=str1[i]; i++; }
printf("The stringl is:%s.\n",str1): printf("The string2 is:%s.\n",str2); return 0: 然后对这个源程序进行编译,编译和执行命令如下: gcc-g-o testtest.c #/test The stringl is:Hello,world. The string2 is:Hello,world?E?Hello,world. 注意上面的命令中多了一个-g选项,该选项的含义是为接下来调试作准备的,如果在 编译时没有加这个选项,那么就不能直接运行gb命令进行调试该程序,不过可以通过另外 种方式来代替它,就是进入gdb以后,在gdb命令输入行输入以下命令来调试该程序: (gdb)gdb test 通过上面的执行结果可以看出,test程序的目的是打印结果应该为: The stringl is:Hello,world. The string2 is:Hello,world. 但实际打印结果却是: The stringl is:Hello,world. The string2 is:Hello,world?E?Hello,world. 通过以上输出的结果可以得知出错的大概位置就在while循环执行过程中,接下来用 gdb进行调试,进入gdb调试界面后会显示如下: (gdb)list 1 #include <stdio.h> y int main() 3 4 char str1[="Hello,world": 5 char str2[11]=""; 6 int i=0: 7 d while(str1[il!=\0') 9 { 10 str2[i]=str1[]; (gdb)list 11 ++, 12 } 13 14 printf("The stringl is:%s.In",str1); 15 printf("The string2 is:%s.\In",str2); 16 return 0: 17 (gdb) Line number 18 out of range;test.c has 17 lines. 其中用st命令用来显示要调适的程序,一般需要好几页才能显示完程序,所以显示下
printf("The string1 is:%s.\n",str1); printf("The string2 is:%s.\n",str2); return 0; } 然后对这个源程序进行编译,编译和执行命令如下: # gcc –g –o test test.c # ./test The string1 is:Hello,world. The string2 is:Hello,world?E?Hello,world. 注意上面的命令中多了一个-g 选项,该选项的含义是为接下来调试作准备的,如果在 编译时没有加这个选项,那么就不能直接运行 gdb 命令进行调试该程序,不过可以通过另外 一种方式来代替它,就是进入 gdb 以后,在 gdb 命令输入行输入以下命令来调试该程序: (gdb) gdb test 通过上面的执行结果可以看出,test 程序的目的是打印结果应该为: The string1 is:Hello,world. The string2 is:Hello,world. 但实际打印结果却是: The string1 is:Hello,world. The string2 is:Hello,world?E?Hello,world. 通过以上输出的结果可以得知出错的大概位置就在 while 循环执行过程中,接下来用 gdb 进行调试,进入 gdb 调试界面后会显示如下: (gdb) list 1 #include <stdio.h> 2 int main() 3 { 4 char str1[]="Hello,world"; 5 char str2[11]=""; 6 int i=0; 7 8 while(str1[i]!='\0') 9 { 10 str2[i]=str1[i]; (gdb) list 11 i++; 12 } 13 14 printf("The string1 is:%s.\n",str1); 15 printf("The string2 is:%s.\n",str2); 16 return 0; 17 } (gdb) Line number 18 out of range; test.c has 17 lines. 其中用 list 命令用来显示要调适的程序,一般需要好几页才能显示完程序,所以显示下