在linux上进行编译调试

1.相关疑问

1. 为什么在代码里使用了一个未定义过的函数(如add()),在编译阶段不会报错,在链接阶段会报错呢?

答:先说几个代码编译的结论:

  • 单个\.c源文件文件被编译成机器码文件时,源文件中的所有变量名以及数组名都会变成地址偏移量;
  • 类型信息都会变成指令的长度(int\-\>subl, 地址\-\>subg);
  • 循环会变成goto的方式实现;
  • 函数的调用变成了使pc指针移动到被调方函数的地址;

由以上第四条可知,函数的调用依赖于被调函数的地址,编译后的文件可以使用nm xxx.o来查看所有函数的地址和函数名的对应情况,在链接之前可以看到此时有的函数名还没有对应的地址,而将这些函数名和地址关联起来的操作就是链接阶段要做的事,在链接阶段无法为主调方找到被调方函数地址时就会报链接错误。
在这里插入图片描述

2. gcc编译器

1. 预处理指令

  • #include:引入头文件

  • #define:定义宏常量和宏函数

  • #if:根据指定条件判断是否编译后续代码块(可作为测试代码开关

    // 使用示例:
    #define DEBUG 1
    #if DEBUG
        // Debugging code
        printf("Debug mode is active.\n");
    #endif
    
  • #ifdef:判断某个标识符是否已经定义(可作为测试代码开关

    #ifdef ON //表示如果定义了ON,或命令行编译时用-D传了ON,就执行下面的输出
        printf("ON is defined!\n");
    #else
        printf("ON is not defined!\n");
    #endif
        printf("main exit\n");
    

    可以在命令行定义预处理器宏gcc -o test test.c -DON

  • #ifndef:判断某个标识符是否没有已经定义(可用于头文件保护

    #ifndef TEST_H
        #define TEST_H
    #endif
    
  • #endif:结束条件编译的代码块

2. gcc常用指令

补充

列出所有函数:nm test.o

查看可执行程序链接了哪些库:ldd test

  • 预处理:

    gcc -E test.c -o test.i
    
  • 编译:

    gcc -S test.c -o test.s
    
  • 汇编:

    // 方式一:从汇编文件到机器码文件
    as test.s -o test.o
    // 方式二:从预处理文件到机器码文件
    gcc-13 -C test.i -o test.o
    // 方式三:从源文件到机器码文件
    gcc-13 -C test.c -o test.o
    
  • 链接:gcc -o test test.c 输出可执行文件

    // 方式一:编译+链接(从源文件到可执行文件)
    gcc -o test test.c
    // 方式二:链接
    gcc -o test test.o
    // 方式三:指定链接路径
    gcc test1.o -o test1 -ladd
    // 还可以使用ld命令可以调用静态链接器
    ld test.o [其他系统库文件] -o test
    
  • 定义宏:

    gcc test1.o -o test1 -D DEBUG
    
  • 制定优化级别:

    gcc test1.o -o test1 -O0 // 推荐O1级别
    
  • 为gdb补充符号信息:

    gcc test1.o -o test1 -O0 -g // 要用gdb调试时最好指定不优化,避免机器码和代码不一致影响调试
    
  • 提示警告:

    gcc test1.o -o test1 -Wall // 注意Wall是大写W
    
  • 指定头文件搜路径:

    gcc test1.o -o test1 -I "../h" //默认从当前路径下搜索
    

3. gdb调试

补充

用gdb调试时,传递命令行参数的两种方式:

  • 方式一:进入gdb后:用set args xxx
  • 方式二:进入gdb前:使用gdb --args test xxx启动

1. 常用指令

  1. 用-g生成可执行文件:gcc –o test test.c -O0 –g

  2. 进入调试器:gdb test

  3. 显示代码:

    • 默认显示:l/list //默认显示10行
    • 显示指定信息:l/list [文件名:]行号or函数名 //[]表示可有可无
  4. 运行:r/run

  5. 退出:q/quit

  6. 断点相关:

    • 设置断点:b/break 4 //在第四行设置断点
    • 列出断点:i b/info break // 查看断点号
    • 删除断点:delete 断点号
    • 停止断点:disable 断点号
    • 激活断点:enable 断点号
  7. 跳转:

    • 下一步不进入函数:n/next //F10
    • 下一步进入函数:s/step //F11
    • 到下一个断点:c/continue
    • 跳出当前函数:finsh
  8. 查看信息:

    • 打印变量:p/print
    • 自动显示的表达式内容:display 表达式 (自动显示内存:display /1xw &i``)
    • 停止显示某个表达式:undisplay 表达式 或者 undisplay 编号(通过info display查看编号)
    • 查看调用堆栈:b t/back trace
    • 查看内存:x<n/f/u> //n表示内存的长度 f表示内存的格式 u表示内存的单位
    • 清空信息: Ctrl + L 组合键,或者输入 shell clear 命令(shell命令用于调用系统断点shell

2. 调试core文件

  1. 启用 core 文件自动生成
    • 查看core文件是否存在限制:ulimit -a
    • 关闭限制:ulimit -c unlimited
  2. 运行程序并生成 core 文件
    • 如果未生成,则使用man core查看帮助文档解决;
  3. 使用 GDB 调试 core 文件:gdb test core;
  4. 查看调试信息
    • 查看调用栈:bt
    • 查看栈帧信息:frame 0
    • 显示寄存器的值:info registers
    • 分析内存:x

4. 静态库和动态库

库文件其实就是别人造好的“轮子”,别人写好并编译好后给用户使用的二进制代码。

静态库文件在程序的链接阶段被需要,而动态库文件在程序运行过程中也被需要。

1. 静态库

在程序链接阶段,库文件会被打包进最终的可执行程序。

gcc编译时,如果存在同名的动态(.so)和静态(.a)库文件,默认是使用动态文件,此时要使用静态库文件就必须要使用-static参数指定优先静态链接,如果找不对应的\.a文件会链接失败。

特点:省心,但体积大且更新不方便。

打包命令

// 1. 得到编译后的机器码文件
gcc -c add.c -o add.o 
// 2. 生成静态库文件(库文件必须以lib开头)
ar crsv libadd.a add.o
// 3. 将静态库文件移动到"/usr/lib"或"/usr/local/lib"下,推荐前者
sudo mv libadd.a /usr/lib
// 4. 使用即可
gcc main.o -o main -ladd

2. 动态库

链接阶段不打包进程序,在程序运行时加载。

特点:体积小、更新方便(动态更新),但容易存在依赖问题。

打包命令

// 1. 生成位置无关的目标代码,使用-fpid(Position Independent Code)
gcc -c add.c -o add.o -fpic
// 2. 生成动态库文件(库文件必须以lib开头)
gcc -shared add.o -o libadd.so
// 3. 将静态库文件移动到"/usr/lib"或"/usr/local/lib"下,推荐前者
sudo mv libadd.so /usr/lib
// 4. 使用即可
gcc main.o -o main -ladd

3. 产品动态更新

原理:利用版本号和软连接实现

  • 第一步:生成带版本好的.so动态库文件,如:libadd.so.0.0.0、libadd.so.0.1.0
  • 第二步:建立最新版本的软连接,sudo ln -s libadd.so.0.1.0 libadd.so

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/358982.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DC-Windows备份(23国赛真题)

2023全国职业院校技能大赛网络系统管理赛项–模块B:服务部署(WindowServer2022) 文章目录 题目配置步骤在DC1上备份系统状态到D:\共享文件夹所有用户具有读/写权限验证查看DC1备份成功的截图在InsideCli上查看备份文件(查看文件夹安全属性)题目 在DC1上备份系统状态到D:\,…

Linux实验记录:使用firewalld

前言&#xff1a; 本文是一篇关于Linux系统初学者的实验记录。 参考书籍&#xff1a;《Linux就该这么学》 实验环境&#xff1a; VmwareWorkStation 17——虚拟机软件 RedHatEnterpriseLinux[RHEL]8——红帽操作系统 备注: RHEL8系统中集成了多款防火墙管理工具&#xf…

Qt之QLabel介绍

概述 QLabel是QT界面中的标签类&#xff0c;它从QFrame下继承&#xff0c;QLabel 类代表标签&#xff0c;它是一个用于显示文本或图像的窗口部件。我们主要介绍一下QLabel的一些简单的使用。 设置颜色背景色和字体的颜色大小 字体及颜色 设置文字使用的是setText函数。 QStri…

一文彻底搞懂redis数据结构及应用

文章目录 1. Redis介绍2.五种基本类型2.1 String字符串2.2 List列表2.3 Set集合2.4 Zset有序集合2.5 Hash散列 3. 三种基本类型3.1 Bitmap &#xff08;位存储&#xff09;3.2 HyperLogLogs&#xff08;基数统计&#xff09;3.3 geospatial (地理位置) 4. Stream详解4.1 Stream…

小土堆pytorch学习笔记002

目录 1、TensorBoard的使用 &#xff08;1&#xff09;显示坐标&#xff1a; &#xff08;2&#xff09;显示图片&#xff1a; 2、Transform的使用 3、常见的Transforms &#xff08;1&#xff09;#ToTensor() &#xff08;2&#xff09;# Normalize() &#xff08;3&…

Java基础—面向对象—19static关键字详解、抽象类、接口、N种内部类

1、static关键字 匿名代码块、静态代码块、构造方法 静态代码块是在类加载的时候执行&#xff0c;仅执行一次 匿名代码块在调用构造函数之前 验证如下图&#xff1a; 2、静态导入包&#xff08;可能很多人听都没听过&#xff09; 3、Math是用final关键字的&#xff0c;fina…

Mybatis-Plus扩展

7 MybatisX插件[扩展] 7.1 MybatisX插件介绍 MybatisX 是一款基于 IDEA 的快速开发插件&#xff0c;为效率而生。 安装方法&#xff1a;打开 IDEA&#xff0c;进入 File -> Settings -> Plugins -> Browse Repositories&#xff0c;输入 mybatisx 搜索并安装。 功…

【Midjourney】如何自定义一套参数

使用Midjourney有时候会遇到需要调整某些参数的时候&#xff0c;例如宽高之类的&#xff1a; --hd --ar 7:4 而Midjourney中提供了一条指令用于自定义一套参数方便重复使用。 以下指令创建一个名为“mine”的选项&#xff0c;翻译过来就是 --hd --ar 7:4: 创建成功后会有类似…

112. 路径总和详解!!三种解法,总有一款适合你(Java)

513.找树左下角的值 题目链接&#xff1a;513. 找树左下角的值 BFS&#xff08;迭代&#xff09;法&#xff1a; /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNod…

在Meteor Lake上测试基于Stable Diffusion的AI应用

上个月刚刚推出的英特尔新一代Meteor Lake CPU&#xff0c;预示着AI PC的新时代到来。AI PC可以不依赖服务器直接在PC端处理AI推理工作负载&#xff0c;例如生成图像或转录音频。这些芯片的正式名称为Intel Core Ultra处理器&#xff0c;是首款配备专门用于处理人工智能任务的 …

外包干了8个月,技术退步明显...

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入武汉某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了四年的功能测…

Java 的 Map 與 List

通過重新new 一個ArrayList 轉化 resTask.setList(new ArrayList<Group>(custMap.values())); 无序的Map List 有序的数据放到Map&#xff0c;就变成无序。 List排序 按照code 的字母进行排序A-Z resTask.getListData().sort(Comparator.comparing(Gmer::getCode));…

深度强化学习(王树森)笔记08

深度强化学习&#xff08;DRL&#xff09; 本文是学习笔记&#xff0c;如有侵权&#xff0c;请联系删除。本文在ChatGPT辅助下完成。 参考链接 Deep Reinforcement Learning官方链接&#xff1a;https://github.com/wangshusen/DRL 源代码链接&#xff1a;https://github.c…

【论文阅读|半监督小苹果检测方法S3AD】

论文题目 &#xff1a; : Semi-supervised Small Apple Detection in Orchard Environments 项目链接&#xff1a;https://www.inf.uni-hamburg.de/en/inst/ab/cv/people/wilms/mad.html 摘要&#xff08;Abstract&#xff09; 农作物检测是自动估产或水果采摘等精准农业应用不…

盘点热门的GPTS智能体,生产力远超原生ChatGPT4

OPENAI开放了GPTS智能体商店&#xff0c;类似于appstore的应用商店&#xff0c;在GPTS商店里面你可以发现并创建自定义版本的ChatGPT&#xff0c;这些版本结合了指令、额外知识和任何技能组合&#xff01; 本周精选 GPTS智能体不仅可以通过API的方式将你的私有化的数据和能力…

双链表的基本知识以及增删查改的实现

满怀热忱&#xff0c;前往梦的彼岸 前言 之前我们对单链表进行了非常细致的剖析&#xff0c;现在我们所面临的则是与之相对应的双链表&#xff0c;我会先告诉诸位它的基本知识&#xff0c;再接着把它的增删查改讲一下&#xff0c;ok&#xff0c;正文开始。 一.链表的种类 我…

机器学习和深度学习中的normalization(归一化)

在机器学习和深度学习中&#xff0c;normalization&#xff08;归一化&#xff09;是一种重要的数据预处理步骤&#xff0c;它的目的是改变数值数据的形式&#xff0c;以使其在一个固定的范围内&#xff0c;通常是 0 到 1&#xff0c;或者使其均值为 0&#xff0c;标准差为 1。…

Jenkins+Python自动化测试持续集成详细教程

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

基于Prompt Learning的信息抽取

PTR: Prompt Tuning with Rules for Text Classification 清华&#xff1b;liuzhiyuan&#xff1b;通过规则制定subpromptRelation Extraction as Open-book Examination: Retrieval-enhanced Prompt Tuning Relation Extraction as Open-book Examination: Retrieval-enhance…

JSP在线阅读系统myeclipse定制开发SQLServer数据库网页模式java编程jdbc

一、源码特点 JSP 小说在线阅读系统是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库 &#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为SQLServer2008&#…