【Linux】使用gcc调试程序

【Liunx学习记录篇】-持续更新中~


篇一:【Linux】VMware安装unbuntu18.04虚拟机-超详细步骤(附镜像文件)
篇二:【Linux】ubuntu18.04系统基础配置及操作
篇三:【Linux】用户与组的操作详细介绍
篇四:【Linux】管理Linux文件权限属性介绍
篇五:【Linux】使用数字表示法和文件表示法修改文件权限(超详细)
篇六:【Linux】配置网络和firewall防火墙(超详细介绍+实战)

文章目录

  • 一.安装gcc
    • 1.认识gcc
    • 2.安装gcc
      • 1.检查是否安装gcc
      • 2.使用yum命令安装gcc
  • 二.编译与测试单一程序
    • 1.编辑程序代码即源码
    • 2.开始编译与测试运行
  • 三.编译与链接主程序和子程序
    • 1.撰写主程序、子程序
    • 2.编译与链接程序
  • 四.调用外部函数库:加入链接的函数库
    • 1.编写一个计算三角函数的sin90°的程序
  • 五.使用gcc(编译、参数与链接)
    • 1.仅将原始码编译为目标文件
    • 2.优化编译时的执行速度
    • 3.将链接的函数库填入
    • 4.将编译的结果生成某个特定的文件
    • 5.在编译时,输出较多的信息说明
  • 六.总结

一.安装gcc

1.认识gcc

【Linux】使用gcc调试程序_第1张图片

GNU编译器集合(GNU Compiler Collection,gcc)是一套由GNU开发的编程语言编译器。它是一套GNU编译器套装,是以GPL许可证发行的自由软件,也是GNU计划的关键部分。gcc原本作为GNU操作系统的官方编译器,现已被大多数UNIX操作系统(如Linux、BSD、macOS等)采纳为标准的编译器。gcc同样适用于微软的Windows操作系统。

gcc原名为GNU C语言编译器,因为它原本只能处理C语言。但gcc后来得到扩展,变得既可以处理C++,又可以处理Fortran、GO.Objective-C/D,以及Ada与其他语言。

2.安装gcc

1.检查是否安装gcc

[root@master ~]# rpm -qa|grep gcc
libgcc-4.8.5-16.0.3.el7_4.2.x86_64

在这里插入图片描述
上述结果表示没有安装gcc

2.使用yum命令安装gcc

yum install gcc

安装完之后,我们再使用上面的rpm命令检查是否有软件包

[root@master etc]# rpm -qa|grep gcc
gcc-4.8.5-44.0.3.el7.x86_64
libgcc-4.8.5-44.0.3.el7.x86_64
[root@master etc]# 

【Linux】使用gcc调试程序_第2张图片
如图所示就是成功安装gcc

二.编译与测试单一程序

1.编辑程序代码即源码

[root@master test]# vim hello.c //用c语言写的程序扩展名建议用.c
[root@master test]# cat hello.c 
#include 
int main(void)
{
	printf("Hello World\n");
}
[root@master test]# 

上面是用C语言的语法写成的一个程序文件。第一行的"#"并不是注解

2.开始编译与测试运行

[root@master test]# gcc hello.c 
[root@master test]# ll hello.c a.out 
-rwxr-xr-x 1 root root 8560 511 17:11 a.out  <==此时会生成这个文件名
-rw-r--r-- 1 root root   65 511 17:10 hello.c
[root@master test]# ./a.out 
Hello World <==运行结果
[root@master test]# 

在正常情况下,直接以gcc编译源码,并且没有加上任何参数,则可执行文件的文件名就会自动设置为a.out,并且能够执行./a.out这个可执行文件

将上面的例子的生成目标文件(Object File)来进行其他操作,而且可执行文件的文件名也不要用默认的a.out,可以使用以下命令:

[root@master test]# gcc -c hello.c 
[root@master test]# ll hello*
-rw-r--r-- 1 root root   65 511 17:10 hello.c
-rw-r--r-- 1 root root 1496 511 17:16 hello.o <==这就是生成的目标文件
[root@master test]# gcc -o hello hello.o <==小写字母o
[root@master test]# ll hello*
-rwxr-xr-x 1 root root 8560 511 17:16 hello  <==这就是可执行文件(-o的结果)
-rw-r--r-- 1 root root   65 511 17:10 hello.c
-rw-r--r-- 1 root root 1496 511 17:16 hello.o
[root@master test]# ./hello 
Hello World
[root@master test]# 

以上例子主要是利用hello.o这个目标文件生成一个名为hello的可执行文件,可以得到hello以及hello.o两个文件,真正可以执行的是hello这个二进制文件

三.编译与链接主程序和子程序

1.撰写主程序、子程序

主程序:

[root@master test]# vim thanks.c
[root@master test]# cat thanks.c 
#include 
int main(void)
{
	printf("Hello World\n");
	thanks_2();
}

下面的thanks_2()就是要调用的子程序:

[root@master test]# vim thanks_2.c
[root@master test]# cat thanks_2.c 
#include 
void thanks_2(void)
{
	printf("Thank you!\n");
}
[root@master test]# 

2.编译与链接程序

1.将源码编译为可执行的二进制文件(警告内容可忽略):

[root@master test]# gcc -c thanks.c thanks_2.c 
[root@master test]# ll
total 16
-rw-r--r-- 1 root root   68 511 17:26 thanks_2.c
-rw-r--r-- 1 root root 1504 511 17:28 thanks_2.o  <==编译生成的目标文件
-rw-r--r-- 1 root root   77 511 17:23 thanks.c
-rw-r--r-- 1 root root 1560 511 17:28 thanks.o   <==编译生成的目标文件
[root@master test]# gcc -o thanks thanks.o thanks_2.o   <==小写字母o
[root@master test]# ll thanks
-rwxr-xr-x 1 root root 8632 511 17:29 thanks <==最终生成的可执行文件

2.运行可执行文件:

[root@master test]# ./thanks 
Hello World
Thank you!
[root@master test]# 

3.如果想要程序在运行的时候具有比较好的性能,或者是其他的调试功能,则可以在编译过程中加入适当的选项,例如:

[root@master test]# gcc -O -c thanks.c thanks_2.c  <== -O为生成优化的选项
[root@master test]# gcc -Wall -c thanks.c thanks_2.c
thanks.c: 在函数‘main’中:
thanks.c:5:2: 警告:隐式声明函数‘thanks_2’ [-Wimplicit-function-declaration]
  thanks_2();
  ^
thanks.c:6:1: 警告:在有返回值的函数中,控制流程到达函数尾 [-Wreturn-type]
 }
 ^
[root@master test]# 

上方代码的-Wall 是显示更详细的编译过程信息。上面的信息为警告信息,不用理会也没关系。

四.调用外部函数库:加入链接的函数库

1.编写一个计算三角函数的sin90°的程序

[root@master test]# vim sin.c
[root@master test]# cat sin.c
#include 
int main(void)
{
	
	float value;
	value = sin ( 3.14/ 2 );
	printf("%f\n",value);
}

[root@master test]# 

我们这样正常编译这个文件,会出现以下错误:

[root@master test]# gcc sin.c 
sin.c: 在函数‘main’中:
sin.c:6:10: 警告:隐式声明与内建函数‘sin’不兼容 [默认启用]
  value = sin ( 3.14/ 2 );
          ^
[root@master test]# 

这是因为C语言中的sin函数是写在libm.so函数库中的,而我们并没有将函数库加进去,我们对源代码进行这样更正:

[root@master test]# vim sin.c
[root@master test]# cat sin.c 
#include 
#include 
int main(void)
{
	
	float value;
	value = sin ( 3.14/ 2 );
	printf("%f\n",value);
}

[root@master test]# gcc sin.c -lm -L/lib -L/user/lib   <==重点在 -lm
[root@master test]# ./a.out  <==尝试执行新文件
1.000000
[root@master test]# 

-lm的解释:

  • -l:加入某个函数库(library)
  • -m:是libm.so函数库,其中,lib与扩展名(.a或.so)不需要写

五.使用gcc(编译、参数与链接)

1.仅将原始码编译为目标文件

仅将原始码编译为目标文件,并不制作链接等功能

[root@master test]# gcc -c hello.c

上述程序会自动生成hello.o文件,但不会生成二进制可执行文件

2.优化编译时的执行速度

在编译时,依据作业环境执行速度:

[root@master test]# gcc -O hello.c -c

上述程序会自动生成hello.o文件,并且进行优化

3.将链接的函数库填入

[root@master test]# gcc sin.c -lm -L/usr/lib -I/usr/include
  • 在最终链接成二进制可执行文件时,这个命令经常执行
  • -lm 指的是libm.so或libm.a函数库文件
  • -L后面接的路径是函数库的搜索目录。
  • -I后面接的是源码内的include文件所在的目录

4.将编译的结果生成某个特定的文件

gcc -o hello hello.c

5.在编译时,输出较多的信息说明

gcc -o hello hello.c -Wall

加入-Wall之后,程序的编译会变得较为严谨,所以警告信息也会显示出来

通常称-Wall或者-O这些非必要的选项为标志。因为我们使用的是C语言,有时也会简称这些标志为CFLAGS

六.总结

程序写好了接下来做的就是调试程序,程序的调试对于程序员或者Linux管理员来说也是至关重要的。
后期会持续更新我学习Linux以及在运维领域的学习记录,如果本篇文章对你有帮助,恳请大家支多多支持哦~

你可能感兴趣的:(linux学习基础,linux,运维,服务器)