Linux编译C程序

  • 原创
  • Madman
  • /
  • 2018-05-15 09:07
  • /
  • 0
  • 398 次阅读

Linux编译C程序-min.png

Synopsis: 分析了Linux环境下从创建C语言源代码到最终的可执行文件的整个过程,中间经过于处理器的预处理阶段(源文件到预处理文件),编译器的编译阶段(预处理文件到汇编文件),汇编器的汇编阶段(汇编文件到可重定向的目标文件),链接器的链接阶段(可重定向的目标文件到可执行的目标文件)。另外简单地介绍了gdb调试工具

1. 创建源代码

可以使用vimnano工具编辑源代码文件:

[root@CentOS ~]# vim hello.c

内容如下:
#include <stdio.h>
int main(){
    printf("Hello, World!\n");
    return 0;
}

vim一般模式下(按ESC退出编辑模式),输入:%!xxd可以查看hello.c的16进制形式,如果要回到文本格式则输入:%!xxd -r。如果输入:%!xxd -b可以查看hello.c的二进制形式,这是hello.c保存在磁盘上的存储状态。

2. 编译与运行

[root@CentOS ~]# yum -y install gcc

gcc命令的基本用法为gcc [options] [filenames],如果只指定源代码文件名而不使用任何选项时,gcc将会自动编译产生一个a.out的可执行文件:

[root@CentOS ~]# gcc hello.c
[root@CentOS ~]# ls -l
-rw-r--r--  1 root root        78 Jan 13 09:45 hello.c
-rwxr-xr-x  1 root root     34749 Jan 13 09:41 a.out
[root@CentOS ~]# ./a.out
Hello, World!

使用-o选项可以指定编译后生成的文件名:

[root@CentOS ~]# gcc -o hello hello.c
[root@CentOS ~]# ls -l
-rw-r--r--  1 root root        78 Jan 13 09:45 hello.c
-rwxr-xr-x  1 root root      6425 Jan 13 09:46 hello
[root@CentOS ~]# ./hello
Hello, World!

3. 分析过程

c编译过程解析.png

3.1 预处理阶段

使用-E选项只做预处理不编译,当使用这个选项时,预处理器的输出被送到标准输出而不是存储到文件。如果想将预处理的输出存储到文件,可结合-o选项使用,使用如下:

[root@CentOS ~]# gcc -E hello.c -o hello.i
[root@CentOS ~]# ls -l
-rw-r--r--  1 root root        78 Jan 13 09:45 hello.c
-rw-r--r--  1 root root     16738 Jan 13 10:06 hello.i
[root@CentOS ~]# less hello.i
# 1 "hello.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "hello.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 28 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 361 "/usr/include/features.h" 3 4
# 1 "/usr/include/sys/cdefs.h" 1 3 4
# 373 "/usr/include/sys/cdefs.h" 3 4
# 1 "/usr/include/bits/wordsize.h" 1 3 4
# 374 "/usr/include/sys/cdefs.h" 2 3 4
# 362 "/usr/include/features.h" 2 3 4
# 385 "/usr/include/features.h" 3 4
# 1 "/usr/include/gnu/stubs.h" 1 3 4



# 1 "/usr/include/bits/wordsize.h" 1 3 4
# 5 "/usr/include/gnu/stubs.h" 2 3 4




# 1 "/usr/include/gnu/stubs-64.h" 1 3 4
# 10 "/usr/include/gnu/stubs.h" 2 3 4
# 386 "/usr/include/features.h" 2 3 4
# 29 "/usr/include/stdio.h" 2 3 4

3.2 编译阶段

使用-S选项,将C程序编译为汇编语言文件后停止编译,gcc编译产生汇编文件的默认后缀为.s

[root@CentOS ~]# ls -l
-rw-r--r--  1 root root        78 Jan 13 09:45 hello.c
-rw-r--r--  1 root root     16738 Jan 13 10:06 hello.i
[root@CentOS ~]# gcc -S hello.c
[root@CentOS ~]# ls -l
-rw-r--r--  1 root root        78 Jan 13 09:45 hello.c
-rw-r--r--  1 root root     16738 Jan 13 10:06 hello.i
-rw-r--r--  1 root root       445 Jan 13 10:10 hello.s

gcc -S hello.c处,使用C源文件编译,也可以用gcc -S hello.i的预处理文件编译,结果一样。

使用-S编译时,也可以和-o结合使用指定编译产生的汇编语言文件的名字,比如gcc -S hello.i -o hello_s.s

3.3 汇编阶段

使用-c选项,将C源文件或者汇编语言文件编译成可重定向的目标文件(二进制形式),其默认后缀为.o

[root@CentOS ~]# ls -l
-rw-r--r--  1 root root        78 Jan 13 09:45 hello.c
-rw-r--r--  1 root root     16738 Jan 13 10:06 hello.i
-rw-r--r--  1 root root       445 Jan 13 10:10 hello.s
[root@CentOS ~]# gcc -c hello.s
[root@CentOS ~]# ls -l
-rw-r--r--  1 root root        78 Jan 13 09:45 hello.c
-rw-r--r--  1 root root     16738 Jan 13 10:06 hello.i
-rw-r--r--  1 root root      1504 Jan 13 10:13 hello.o
-rw-r--r--  1 root root       445 Jan 13 10:10 hello.s

也可以和-o结合使用指定编译产生的目标文件的名字,比如gcc -c hello.s -o hello.o。由于hello.o是二进制文件,使用less查看时会显示为乱码,使用vim hello.o打开也显示为乱码,按下:%!xxd查看其16进制形式,按下:%!xxd -r退出16进制查看模式,回到乱码状态。在退出vim时,若提示已经修改了文件,则使用:q!强制退出。

3.4 链接阶段

链接器将可重定向的目标文件hello.o以及库文件(如printf.o)执行并入操作,形成最终可执行的可执行目标文件

[root@CentOS ~]# ls -l
-rw-r--r--  1 root root        78 Jan 13 09:45 hello.c
-rw-r--r--  1 root root     16738 Jan 13 10:06 hello.i
-rw-r--r--  1 root root      1504 Jan 13 10:13 hello.o
-rw-r--r--  1 root root       445 Jan 13 10:10 hello.s
[root@CentOS ~]# gcc -o hello hello.o
[root@CentOS ~]# ls -l
-rwxr-xr-x  1 root root      6425 Jan 13 10:16 hello
-rw-r--r--  1 root root        78 Jan 13 09:45 hello.c
-rw-r--r--  1 root root     16738 Jan 13 10:06 hello.i
-rw-r--r--  1 root root      1504 Jan 13 10:13 hello.o
-rw-r--r--  1 root root       445 Jan 13 10:10 hello.s

3.5 执行程序

[root@CentOS ~]# ./hello
Hello, World!

由此可以看出前面使用的gcc hello.c -o hello命令,是将hello.c直接编译为可执行的目标文件,中间经过于处理器的预处理阶段(源文件到预处理文件),编译器的编译阶段(预处理文件到汇编文件),汇编器的汇编阶段(汇编文件到可重定向的目标文件),链接器的链接阶段(可重定向的目标文件到可执行的目标文件)

4. 使用 gdb 工具调试C或C++程序

GNU Debugger

4.1 安装 gdb

[root@CentOS ~]# yum -y install gdb
[root@CentOS ~]# gdb
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-83.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) 

4.2 调试步骤

gdb详细使用说明请执行man gdb,附件里有GDB的官方文档,600多页

参考:

1. 使用 -g 选项重新编译源代码
[root@CentOS ~]# gcc -g factorial.c -o factorial

2. 启动gdb
[root@CentOS ~]# gdb factorial

3. 设置断点,比如在第10行
(gdb) break 10

4. 在gdb中执行程序
(gdb) run

5. 此时可以打印各变量的值
(gdb) p i
(gdb) p j

6. 控制执行过程
c – continue
n - next
s – step
未经允许不得转载: LIFE & SHARE - 王颜公子 » Linux编译C程序

分享

作者

作者头像

Madman

如果博文内容有误或其它任何问题,欢迎留言评论,我会尽快回复; 或者通过QQ、微信等联系我

0 条评论

暂时还没有评论.

发表评论前请先登录