【Linux】使用gcc调试程序

简介: 【Linux】使用gcc调试程序

一.安装gcc


1.认识gcc



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]# 


如图所示就是成功安装gcc


二.编译与测试单一程序


1.编辑程序代码即源码


[root@master test]# vim hello.c //用c语言写的程序扩展名建议用.c
[root@master test]# cat hello.c 
#include <stdio.h>
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 5月  11 17:11 a.out  <==此时会生成这个文件名
-rw-r--r-- 1 root root   65 5月  11 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 5月  11 17:10 hello.c
-rw-r--r-- 1 root root 1496 5月  11 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 5月  11 17:16 hello  <==这就是可执行文件(-o的结果)
-rw-r--r-- 1 root root   65 5月  11 17:10 hello.c
-rw-r--r-- 1 root root 1496 5月  11 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 <stdio.h>
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 <stdio.h>
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 5月  11 17:26 thanks_2.c
-rw-r--r-- 1 root root 1504 5月  11 17:28 thanks_2.o  <==编译生成的目标文件
-rw-r--r-- 1 root root   77 5月  11 17:23 thanks.c
-rw-r--r-- 1 root root 1560 5月  11 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 5月  11 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 <stdio.h>
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 <stdio.h>
#include <math.h>
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


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管理员来说也是至关重要的。

目录
相关文章
|
1月前
|
安全 Linux Shell
Linux上执行内存中的脚本和程序
【9月更文挑战第3天】在 Linux 系统中,可以通过多种方式执行内存中的脚本和程序:一是使用 `eval` 命令直接执行内存中的脚本内容;二是利用管道将脚本内容传递给 `bash` 解释器执行;三是将编译好的程序复制到 `/dev/shm` 并执行。这些方法虽便捷,但也需谨慎操作以避免安全风险。
|
2月前
|
网络协议 Linux
Linux查看端口监听情况,以及Linux查看某个端口对应的进程号和程序
Linux查看端口监听情况,以及Linux查看某个端口对应的进程号和程序
145 2
|
2月前
|
Linux Python
linux上根据运行程序的进程号,查看程序所在的绝对路径。linux查看进程启动的时间
linux上根据运行程序的进程号,查看程序所在的绝对路径。linux查看进程启动的时间
47 2
|
8天前
|
消息中间件 分布式计算 Java
Linux环境下 java程序提交spark任务到Yarn报错
Linux环境下 java程序提交spark任务到Yarn报错
18 5
|
2月前
|
NoSQL Linux C语言
Linux GDB 调试
Linux GDB 调试
50 10
|
1月前
|
Linux 编译器 C语言
Linux内核对GCC版本的检测
Linux内核对GCC版本的检测
|
2月前
|
NoSQL Linux C语言
嵌入式GDB调试Linux C程序或交叉编译(开发板)
【8月更文挑战第24天】本文档介绍了如何在嵌入式环境下使用GDB调试Linux C程序及进行交叉编译。调试步骤包括:编译程序时加入`-g`选项以生成调试信息;启动GDB并加载程序;设置断点;运行程序至断点;单步执行代码;查看变量值;继续执行或退出GDB。对于交叉编译,需安装对应架构的交叉编译工具链,配置编译环境,使用工具链编译程序,并将程序传输到开发板进行调试。过程中可能遇到工具链不匹配等问题,需针对性解决。
|
2月前
|
Ubuntu Linux
内核实验(四):Qemu调试Linux内核,实现NFS挂载
本文介绍了在Qemu虚拟机中配置NFS挂载的过程,包括服务端的NFS服务器安装、配置和启动,客户端的DHCP脚本添加和开机脚本修改,以及在Qemu中挂载NFS、测试连通性和解决挂载失败的方法。
50 0
内核实验(四):Qemu调试Linux内核,实现NFS挂载
|
2月前
|
Linux API
在Linux中,程序产生了库日志虽然删除了,但磁盘空间未更新是什么原因?
在Linux中,程序产生了库日志虽然删除了,但磁盘空间未更新是什么原因?
|
2月前
|
Linux Windows Python
最新 Windows\Linux 后台运行程序注解
本文介绍了在Windows和Linux系统后台运行程序的方法,包括Linux系统中使用nohup命令和ps命令查看进程,以及Windows系统中通过编写bat文件和使用PowerShell启动隐藏窗口的程序,确保即使退出命令行界面程序也继续在后台运行。
下一篇
无影云桌面