incidentally [InsI5dentElI] adv. 附带地, 顺便提及(学单词一个:)
An object file contains machine code where any references to the memory addresses of functions(orvariables)in other files are left undefined.This allows source files to be compiled without direct reference to each other.The linker fills in these missing addresses when it produces the executable.
This means that the object file which contains the definition of a function should appear after any files which call that function.
A library is a collection of precompiled object files which can be linked into programs. Libraries are typically stored in special archive files with the extension‘.a’, referred to as static libraries.They are created from object files with a separate tool, the GNU archiver ar, and used by the linker to resolve references to functions at compile-time.
additional directories can be added to the link path using the environment variable LIBRARY_PATH.
dir1:dir2:dir3:......
[ 短语:in preference to 优先于... ]
当执行函数动态链接.so时,如果此文件不在缺省目录下‘/usr/local/lib’ and ‘/usr/lib’.
‘-std=iso9899:199409’-- The ISO C language standard with ISO Amendment 1, published
in 1994.
published in 1999 (ISO/IEC9899:1999).
‘-std=gnu89’ and ‘-std=gnu99’. -- for GNU extensions
‘-Wcomment’ This option warns about nested comments.
‘-Wformat’ This option warns about the incorrect use of format strings in functions
such as printf and scanf, where the format specifier does not agree with the
type of the corresponding function argument.
‘-Wunused’ This option warns about unused variables.
‘-Wimplicit’ This option warns about any functions that are used without being declared.
‘-Wreturn-type’ This option warns about functions that are defined without a return
type but not declared void. It also catches empty return statements in
functions that are not declared void.
8. 其他的一些warn编译选项(不包含在Wall中的)
‘-W’ This is a general option similar to ‘-Wall’ which warns about a selection of
一般情况下,-W 和 -Wall同时使用
‘-Wconversion’ This option warns about implicit type conversions that could cause
unexpected results.
‘-Wshadow’ This option warns about the redeclaration of a variable name in a scope where
it has already been declared.
‘-Wcast-qual’ This option warns about pointers that are cast to remove a type qualifier,
such as const.
‘-Wwrite-strings’ This option implicitly gives all string constants defined in the program
a const qualifier, causing a compile-time warning if there is an attempt
to overwrite them.
‘-Wtraditional’ This option warns about parts of the code which would be interpreted
differently by an ANSI/ISO compiler and a “traditional” pre-ANSI
compiler.(5)
上面的这些warn选项都仅仅产生warn,而不会停止编译过程,下面的选项可以将warn视为error并停止编译
‘-Werror’ changes the default behavior by converting warnings into errors, stopping
the compilation whenever a warning occurs.
between signed and unsigned values.
一般情况下,-W 和 -Wall同时使用
‘-Wconversion’ This option warns about implicit type conversions that could cause
unexpected results.
‘-Wshadow’ This option warns about the redeclaration of a variable name in a scope where
it has already been declared.
‘-Wcast-qual’ This option warns about pointers that are cast to remove a type qualifier,
such as const.
‘-Wwrite-strings’ This option implicitly gives all string constants defined in the program
a const qualifier, causing a compile-time warning if there is an attempt
to overwrite them.
‘-Wtraditional’ This option warns about parts of the code which would be interpreted
differently by an ANSI/ISO compiler and a “traditional” pre-ANSI
compiler.(5)
上面的这些warn选项都仅仅产生warn,而不会停止编译过程,下面的选项可以将warn视为error并停止编译
‘-Werror’ changes the default behavior by converting warnings into errors, stopping
the compilation whenever a warning occurs.
第四章:使用预处理器 ( Using the preprocessor )
GCC的预处理器 cpp属于GCC包的一部分;在原文件被编译之前,GCC会使用cpp将所有的宏扩展。
4.1定义宏(macro)
有两种定义的宏的方式:1:其他原文件中;2:在GCC的命令行中使用 -Dxxx
当这些宏被定义后(#define xxx)
在系统中使用时:#ifdef xxx 就会被预处理器扩展为有效代码;
在系统中已经定义了一些系统命名空间内的宏,都是以 __ 开头的(两条下划线)
使用命令:$ cpp -dM /dev/null 可以查看到所有的预定义宏
(注:在这些宏中,有一些是GCC系统级的宏,它们都不是以__开头,这些非标准的宏可以使用
GCC的编译选项 -ansi 使其无效)
(其实,利用-Dxxx来定义xxx,就是将xxx赋值为1 )
4.2 定义有值宏
也是利用 -Dxxx = value的方式来定义
假如利用-DNAME="" (空)来定义一个宏,则这个宏也被视为被定义的,但是如果按值展开的话,
则为空;
4.3 预处理源文件
The ‘-E’ option causes gcc to run the preprocessor, display the expanded
output, and then exit without compiling the resulting source code.
可以利用 -E选项来查看预处理器的工作过程
可以利用 -save-temps选项来保存预处理器的处理过程日志到临时文件xxxx.i;
The preprocessed system header files usually generate a lot of output.
This can be redirected to a file, or saved more conveniently using the gcc
‘-save-temps’ option:
$ gcc -c -save-temps hello.c
After running this command, the preprocessed output will be available
in the file ‘hello.i’. The ‘-save-temps’ option also saves ‘.s’ assembly
files and ‘.o’ object files in addition to preprocessed ‘.i’ files.
第五章:Compiling for debugging
一个可执行文件中并不保存任何与其源文件中相关的函数以及变量信息在其中,可执行文件
只是机器码的集合。
这样的话,如果系统运行过程中出现错误,我们也不能定位错误。
利用 -g 编译选项,可以将这些信息保存在执行文件中,使得我们可以利用gdb工具调试;
保存的信息有:函数名,变量名(及其所有引用)以及它们的相应行号,这些信息都保存
在叫做符号表的东东中;
5.1 Core文件
When a program exits abnormally the operating system can write out a core file,
usually named ‘core’, which contains the in-memory state of the program at the
time it crashed.
当我们运行程序发生错误时,假如提示信息中包含‘core dumped’错误信息时,操作系统
已经产生了一个叫做core的文件到当前目录(或者/var/coredumps/下)
(注:In the GNU Bash shell the command ulimit -c controls the maximum
size of core files. If the size limit is zero, no core files are produced.
命令$ ulimit -c unlimited 使得任何大小的core文件都可以生成,但是这些设置只在
当前shell有效)
使用命令 $ gdb EXECUTABLE-FILE CORE-FILE 来分析
第六章:优化编译
6.1 Source-level optimization 代码级优化
在此只介绍两种:common subexpression elimination和function inlining.
Common subexpression elimination:(CSE)
只要优化开关打开,这种优化都会进行,进行这种优化既可以提高速度,又可以减少
代码大小,例如:
x = cos(v)*(1+sin(u/2)) + sin(w)*(1-sin(u/2))
可以写成:
t = sin(u/2)
x = cos(v)*(1+t) + sin(w)*(1-t)
(利用中间变量减少运算次数)
function inlining:
6.2 Speed-space tradeoffs 速度-空间权衡
6.2.1 Loop unrolling
例如:
for (i = 0; i < 8; i++)
{
y[i] = i;
}
很多的时间花费在判断上,可以改写为:
y[0] = 0;
y[1] = 1;
y[2] = 2;
y[3] = 3;
y[4] = 4;
y[5] = 5;
y[6] = 6;
y[7] = 7;
这样可以达到最快的执行速度(没有判断语句,同时可以利用流水线),但是空间也增大了
另外一例:
for (i = 0; i < n; i++)
{
y[i] = i;
}
可以重新写成:
for (i = 0; i < (n % 2); i++)
{
y[i] = i;
}
for ( ; i + 1 < n; i += 2) /* no initializer */
{
y[i] = i;
y[i+1] = i+1;
}
The first loop handles the case i = 0 when n is odd, and the second loop
handles all the remaining iterations. Note that the second loop does
not use an initializer in the first argument of the for statement, since
it continues where the first loop finishes. The assignments in the second
loop can be parallelized, and the overall number of tests is reduced by a
factor of 2 (approximately). Higher factors can be achieved by unrolling
more assignments inside the loop, at the cost of greater code size.
6.3 scheduling
When scheduling is enabled, instructions must be arranged so that
their results become available to later instructions at the right time, and to
allow for maximum parallel execution. Scheduling improves the speed of
an executable without increasing its size, but requires additional memory
and time in the compilation process itself (due to its complexity).
6.4 优化等级
优化等级分为:0 - 3
编译选项为: -Olevel
各等级含义如下:
‘-O0’ or no ‘-O’ option (default)不优化
At this optimization level GCC does not perform any optimization
and compiles the source code in the most straightforward way
possible. Each command in the source code is converted directly
to the corresponding instructions in the executable file, without
rearrangement. This is the best option to use when debugging a
program.
The option ‘-O0’ is equivalent to not specifying a ‘-O’ option.
‘-O1’ or ‘-O’
This level turns on the most common forms of optimization that
do not require any speed-space tradeoffs. With this option the
resulting executables should be smaller and faster than with ‘-O0’.
The more expensive optimizations, such as instruction scheduling,
are not used at this level.
Compiling with the option ‘-O1’ can often take less time than compiling
with ‘-O0’, due to the reduced amounts of data that need to
be processed after simple optimizations.
‘-O2’ This option turns on further optimizations, in addition to those
used by ‘-O1’. These additional optimizations include instruction
scheduling. Only optimizations that do not require any speed-space
tradeoffs are used, so the executable should not increase in size. The
compiler will take longer to compile programs and require more
memory than with ‘-O1’. This option is generally the best choice
for deployment of a program, because it provides maximum optimization
without increasing the executable size. It is the default
optimization level for releases of GNU packages.
‘-O3’ This option turns on more expensive optimizations, such as function
inlining, in addition to all the optimizations of the lower levels
‘-O2’ and ‘-O1’. The ‘-O3’ optimization level may increase the speed
of the resulting executable, but can also increase its size. Under
some circumstances where these optimizations are not favorable,
this option might actually make a program slower.
‘-funroll-loops’
This option turns on loop-unrolling, and is independent of the other
optimization options. It will increase the size of an executable.
Whether or not this option produces a beneficial result has to be
examined on a case-by-case basis.
‘-Os’ This option selects optimizations which reduce the size of an executable.
The aim of this option is to produce the smallest possible
executable, for systems constrained by memory or disk space. In
some cases a smaller executable will also run faster, due to better
cache usage.
注:For most purposes it is satisfactory to use ‘-O0’ for debugging, and
‘-O2’ for development and deployment.
“optimizations may not necessarily make a program faster in every case.”
第七章:编译C++程序
GCC是一个真正的C++编译器,其直接将C++代码编译为汇编代码。
1。利用g++而不是gcc命令;
(注:C++ source code should be given one of the valid C++ file extensions ‘.cc’,
‘.cpp’, ‘.cxx’ or ‘.C’ rather than the ‘.c’ extension used for C programs.)
2。C++标准库模板
The C++ standard library ‘libstdc++’ supplied with GCC provides a wide
range of generic container classes such as lists and queues, in addition to
generic algorithms such as sorting。
3。Explicit template instantiation
To achieve complete control over the compilation of templates with g++
it is possible to require explicit instantiation of each occurrence of a template,
using the option ‘-fno-implicit-templates’.
第八章:平台相关的选项
利用 -m 选项来确定不同的开发平台
获得GCC的帮助文档:
$ gcc -v --help
$ gcc -v --help 2>&1 | more
获得GCC的版本号:
$ gcc --version
(注:The ‘-v’ option can also be used to display detailed information about the
exact sequence of commands used to compile and link a program)
第十章:编译器相关的工具
1。 ar工具 Creating a library with the GNU archiver
The GNU archiver ar combines a collection of object files into a single
archive file, also known as a library.
ar工具可以将要发布的多个.o文件组装成一个.a的库文件
例如:将hello_fn.o和bye_fn.o生成 libhello.a的命令行:
$ ar cr libhello.a hello_fn.o bye_fn.o
其中The option ‘cr’ stands for “create and replace”.
利用 选项 t 可以查看.a文件中所包含的所有.o的信息
$ ar t libhello.a
hello_fn.o
bye_fn.o
2。程序性能测试工具-gprof
To use profiling, the program must be compiled and linked with the ‘-pg’
profiling option:
$ gcc -Wall -c -pg collatz.c
$ gcc -Wall -pg collatz.o
编译和链接的时候添加选项 -pg ,才能使用gprof测试程序性能
然后运行编译通过的程序,才能产生gprof需要的文件 gmon.out(在当前目录下)
然后执行:
$ gprof a.out (假设可执行文件是缺省生成的)
3。程序覆盖测试工具- gcov
The GNU coverage testing tool gcov analyses the number of times each
line of a program is executed during a run. This makes it possible to
find areas of the code which are not used, or which are not exercised
in testing. When combined with profiling information from gprof the
information from coverage testing allows efforts to speed up a program to
be concentrated on specific lines of the source code.
编译和链接必须使用相关选项,才可以使用gcov工具。
例如:
$ gcc -Wall -fprofile-arcs -ftest-coverage cov.c
其中
‘-ftest-coverage’ adds instructions for counting the number of times
individual lines are executed,
‘-fprofile-arcs’ incorporates instrumentation code for each branch of
the program. Branch instrumentation records how frequently
different paths are taken through‘if’ statements and
other conditionals.
运行通过编译的程序,产生供gcov使用的文件:
分别带有后缀:‘.bb’‘.bbg’ and ‘.da’在当前目录下
然后运行
$ gcov cov.c (注意:是源代码文件)
这样会产生一个带有标注的源文件的副本文件,后缀为 .gcov
在该文件中,标注了每一行代码的执行次数,标注为‘######’的语句为
未被执行到的语句。
可以通过命令:
grep ’######’ *.gcov 查找到所有未被执行到的语句
第十一章:编译器工作过程
Compilation is a multi-stage process involving several
tools, including the GNU Compiler itself (through the gcc or g++ frontends),
the GNU Assembler as, and the GNU Linker ld. The complete
set of tools used in the compilation process is referred to as a toolchain.
toolchain的定义见此:)
调用GCC的内部过程如下:
• preprocessing (to expand macros) 预处理
• compilation (from source code to assembly language) 编译
• assembly (from assembly language to machine code) 汇编
• linking (to create the final executable) 链接
详细描述如下:
1。preprocessing:
举例:第一步GCC会调用如下命令
$ cpp hello.c > hello.i
生成中间文件 hello.i(如果是C++文件的话,就是 hello.ii)
这种中间文件不会保存到磁盘上的,除非添加了编译选项-save-temps
2。compilation:
第二步:调用gcc(或者g++)生成汇编文件而不是.o文件(使用了-S选项)
$ gcc -Wall -S hello.i
这样就生成了基于x86 CPU的汇编文件 hello.s
3.assembly:
The purpose of the assembler is to convert assembly language into machine
code and generate an object file. When there are calls to external
functions in the assembly source file, the assembler leaves the addresses
of the external functions undefined, to be filled in later by the linker.
第三步调用
$ as hello.s -o hello.o
4。linking:
The final stage of compilation is the linking of object files to create an
executable. In practice, an executable requires many external functions
from system and C run-time (crt) libraries. Consequently, the actual link
commands used internally by GCC are complicated.
第四步调用
$ gcc hello.o
其实在GCC内部的这一步调用如下:
$ ld -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o
/usr/lib/crti.o /usr/lib/gcc-lib/i686/3.3.1/crtbegin.o
-L/usr/lib/gcc-lib/i686/3.3.1 hello.o -lgcc -lgcc_eh
-lc -lgcc -lgcc_eh /usr/lib/gcc-lib/i686/3.3.1/crtend.o
/usr/lib/crtn.o(非常复杂)
第十二章:测试编译后文件的工具
1。Identifying files 鉴别文件 - file 命令
举例:
$ file a.out
a.out: ELF 32-bit LSB executable, Intel 80386,
version 1 (SYSV), dynamically linked (uses shared
libs), not stripped
最后一个not stripped表示该文件含符号表(可以利用命令strip去除符号表)
2。查看符号表工具 - nm
举例:
vides maximum optimization
without increasing the executable size. It is the default
optimization level for releases of GNU packages.
‘-O3’ This option turns on more expensive optimizations, such as function
inlining, in addition to all the optimizations of the lower levels
‘-O2’ and ‘-O1’. The ‘-O3’ optimization level may increase the speed
of the resulting executable, but can also increase its size. Under
some circumstances where these optimizations are not favorable,
this option might actually make a program slower.
‘-funroll-loops’
This option turns on loop-unrolling, and is independent of the other
optimization options. It will increase the size of an executable.
Whether or not this option produces a beneficial result has to be
examined on a case-by-case basis.
‘-Os’ This option selects optimizations which reduce the size of an executable.
The aim of this option is to produce the smallest possible
executable, for systems constrained by memory or disk space. In
some cases a smaller executable will also run faster, due to better
cache usage.
注:For most purposes it is satisfactory to use ‘-O0’ for debugging, and
‘-O2’ for development and deployment.
“optimizations may not necessarily make a program faster in every case.”
第七章:编译C++程序
GCC是一个真正的C++编译器,其直接将C++代码编译为汇编代码。
1。利用g++而不是gcc命令;
(注:C++ source code should be given one of the valid C++ file extensions ‘.cc’,
‘.cpp’, ‘.cxx’ or ‘.C’ rather than the ‘.c’ extension used for C programs.)
2。C++标准库模板
The C++ standard library ‘libstdc++’ supplied with GCC provides a wide
range of generic container classes such as lists and queues, in addition to
generic algorithms such as sorting。
3。Explicit template instantiation
To achieve complete control over the compilation of templates with g++
it is possible to require explicit instantiation of each occurrence of a template,
using the option ‘-fno-implicit-templates’.
第八章:平台相关的选项
利用 -m 选项来确定不同的开发平台
获得GCC的帮助文档:
$ gcc -v --help
$ gcc -v --help 2>&1 | more
获得GCC的版本号:
$ gcc --version
(注:The ‘-v’ option can also be used to display detailed information about the
exact sequence of commands used to compile and link a program)
第十章:编译器相关的工具
1。 ar工具 Creating a library with the GNU archiver
The GNU archiver ar combines a collection of object files into a single
archive file, also known as a library.
ar工具可以将要发布的多个.o文件组装成一个.a的库文件
例如:将hello_fn.o和bye_fn.o生成 libhello.a的命令行:
$ ar cr libhello.a hello_fn.o bye_fn.o
其中The option ‘cr’ stands for “create and replace”.
利用 选项 t 可以查看.a文件中所包含的所有.o的信息
$ ar t libhello.a
hello_fn.o
bye_fn.o
2。程序性能测试工具-gprof
To use profiling, the program must be compiled and linked with the ‘-pg’
profiling option:
$ gcc -Wall -c -pg collatz.c
$ gcc -Wall -pg collatz.o
编译和链接的时候添加选项 -pg ,才能使用gprof测试程序性能
然后运行编译通过的程序,才能产生gprof需要的文件 gmon.out(在当前目录下)
然后执行:
$ gprof a.out (假设可执行文件是缺省生成的)
3。程序覆盖测试工具- gcov
The GNU coverage testing tool gcov analyses the number of times each
line of a program is executed during a run. This makes it possible to
find areas of the code which are not used, or which are not exercised
in testing. When combined with profiling information from gprof the
information from coverage testing allows efforts to speed up a program to
be concentrated on specific lines of the source code.
编译和链接必须使用相关选项,才可以使用gcov工具。
例如:
$ gcc -Wall -fprofile-arcs -ftest-coverage cov.c
其中
‘-ftest-coverage’ adds instructions for counting the number of times
individual lines are executed,
‘-fprofile-arcs’ incorporates instrumentation code for each branch of
the program. Branch instrumentation records how frequently
different paths are taken through‘if’ statements and
other conditionals.
运行通过编译的程序,产生供gcov使用的文件:
分别带有后缀:‘.bb’‘.bbg’ and ‘.da’在当前目录下
然后运行
$ gcov cov.c (注意:是源代码文件)
这样会产生一个带有标注的源文件的副本文件,后缀为 .gcov
在该文件中,标注了每一行代码的执行次数,标注为‘######’的语句为
未被执行到的语句。
可以通过命令:
grep ’######’ *.gcov 查找到所有未被执行到的语句
第十一章:编译器工作过程
Compilation is a multi-stage process involving several
tools, including the GNU Compiler itself (through the gcc or g++ frontends),
the GNU Assembler as, and the GNU Linker ld. The complete
set of tools used in the compilation process is referred to as a toolchain.
toolchain的定义见此:)
调用GCC的内部过程如下:
• preprocessing (to expand macros) 预处理
• compilation (from source code to assembly language) 编译
• assembly (from assembly language to machine code) 汇编
• linking (to create the final executable) 链接
详细描述如下:
1。preprocessing:
举例:第一步GCC会调用如下命令
$ cpp hello.c > hello.i
生成中间文件 hello.i(如果是C++文件的话,就是 hello.ii)
这种中间文件不会保存到磁盘上的,除非添加了编译选项-save-temps
2。compilation:
第二步:调用gcc(或者g++)生成汇编文件而不是.o文件(使用了-S选项)
$ gcc -Wall -S hello.i
这样就生成了基于x86 CPU的汇编文件 hello.s
3.assembly:
The purpose of the assembler is to convert assembly language into machine
code and generate an object file. When there are calls to external
functions in the assembly source file, the assembler leaves the addresses
of the external functions undefined, to be filled in later by the linker.
第三步调用
$ as hello.s -o hello.o
4。linking:
The final stage of compilation is the linking of object files to create an
executable. In practice, an executable requires many external functions
from system and C run-time (crt) libraries. Consequently, the actual link
commands used internally by GCC are complicated.
第四步调用
$ gcc hello.o
其实在GCC内部的这一步调用如下:
$ ld -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o
/usr/lib/crti.o /usr/lib/gcc-lib/i686/3.3.1/crtbegin.o
-L/usr/lib/gcc-lib/i686/3.3.1 hello.o -lgcc -lgcc_eh
-lc -lgcc -lgcc_eh /usr/lib/gcc-lib/i686/3.3.1/crtend.o
/usr/lib/crtn.o(非常复杂)
第十二章:测试编译后文件的工具
1。Identifying files 鉴别文件 - file 命令
举例:
$ file a.out
a.out: ELF 32-bit LSB executable, Intel 80386,
version 1 (SYSV), dynamically linked (uses shared
libs), not stripped
最后一个not stripped表示该文件含符号表(可以利用命令strip去除符号表)
2。查看符号表工具 - nm
举例:
$ nm a.out
08048334 t Letext
08049498 ? _DYNAMIC
08049570 ? _GLOBAL_OFFSET_TABLE_
........
080483f0 T main
08049590 b object.11
0804948c d p.3
U
printf@GLIBC_2.0
其中: T表示该函数在此文件中有定义
U表示未定义的函数(需要link的外部函数)
所以,nm最常用的地方在于,查看这个文件中是否包含某函数的定义
3。寻找所需的动态链接库工具 - ldd
例如:
$ gcc -Wall hello.c
$ ldd a.out
libc.so.6 => /lib/libc.so.6 (0x40020000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
给命令同样可以用于动态链接库本身,来查找其所需要的链接库