在 Linux 上调试 C++ 程序

news2025/1/8 15:33:52

在 Linux 上调试 C++ 程序是一个常见的开发任务,Linux 提供了多种强大的工具来帮助你进行调试。以下是常用的调试方法和工具.

1. 使用 GDB (GNU Debugger)

GDB 是最常用且功能强大的命令行调试器,适用于 C、C++ 和其他语言。它允许你逐步执行代码、设置断点、检查变量值、查看调用栈等。

安装 GDB

大多数 Linux 发行版默认已经安装了 GDB。如果没有,可以通过包管理器安装:

  • Debian/Ubuntu:

    sudo apt-get install gdb
    
  • Fedora/CentOS/RHEL:

    sudo dnf install gdb
    
  • Arch Linux:

    sudo pacman -S gdb
    
编译带有调试信息的程序

为了使 GDB 能够提供详细的调试信息,你需要在编译时添加 -g 选项,以便生成调试符号。

g++ -g -o my_program my_program.cpp
启动 GDB

你可以通过以下方式启动 GDB

  • 直接运行程序

    gdb ./my_program
    
  • 附加到正在运行的进程(如果你需要调试一个已经在运行的程序):

    gdb -p <pid>
    
常用 GDB 命令
  • run [args]: 开始运行程序,传递参数(如果有)。

    (gdb) run arg1 arg2
    
  • break <function>break <file:line>: 设置断点。

    (gdb) break main
    (gdb) break my_function
    (gdb) break my_file.cpp:10
    
  • continuec: 继续执行程序,直到遇到下一个断点或异常。

    (gdb) continue
    
  • steps: 单步执行,进入函数内部。

    (gdb) step
    
  • nextn: 单步执行,不进入函数内部。

    (gdb) next
    
  • print <expression>p <expression>: 打印变量或表达式的值。

    (gdb) print x
    (gdb) print my_object->get_value()
    
  • backtracebt: 显示当前调用栈。

    (gdb) backtrace
    
  • info locals: 显示当前作用域中的局部变量。

    (gdb) info locals
    
  • info args: 显示当前函数的参数。

    (gdb) info args
    
  • watch <expression>: 设置监视点,当表达式的值发生变化时暂停程序。

    (gdb) watch x
    
  • delete <breakpoint-number>: 删除指定编号的断点。

    (gdb) delete 1
    
  • quitq: 退出 GDB。

    (gdb) quit
    
示例:调试一个简单的 C++ 程序

假设你有一个简单的 C++ 程序 main.cpp

#include <iostream>

void foo() {
    int a = 5;
    int b = 0;
    int c = a / b;  // 这里会触发除零错误
}

int main() {
    foo();
    std::cout << "Program finished." << std::endl;
    return 0;
}
  1. 编译程序

    g++ -g -o my_program main.cpp
    
  2. 启动 GDB

    gdb ./my_program
    
  3. 设置断点并运行程序

    (gdb) break foo
    (gdb) run
    
  4. 单步执行

    (gdb) step
    
  5. 查看变量值

    (gdb) print a
    (gdb) print b
    
  6. 继续执行,直到遇到除零错误

    (gdb) continue
    
  7. 查看调用栈

    (gdb) backtrace
    

2. 使用 Visual Studio Code (VSCode) 调试

VSCode 提供了一个图形化的调试界面,结合 GDB 或 LLDB,可以更方便地调试 C++ 程序。以下是如何在 VSCode 中配置和使用调试器的步骤。

安装必要的扩展
  1. 安装 C/C++ 扩展

    • 打开 VSCode。
    • 点击左侧活动栏中的扩展图标(四个方块组成的图标)。
    • 搜索并安装 C/C++ 扩展(由 Microsoft 提供)。
  2. 安装调试器

    • 对于 GDB,确保系统上已经安装了 gdb
    • 对于 LLDB,确保系统上已经安装了 lldb
配置 launch.json

在项目的根目录下创建 .vscode 文件夹,并在其中创建 launch.json 文件。这个文件用于配置调试器的启动参数。

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/my_program",  // 你的可执行文件路径
            "args": [],  // 传递给程序的参数
            "stopAtEntry": false,  // 是否在程序入口处停止
            "cwd": "${workspaceFolder}",  // 工作目录
            "environment": [],
            "externalConsole": false,  // 是否在外部终端中运行
            "MIMode": "gdb",  // 使用的调试器 (gdb 或 lldb)
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "build",  // 可选:在调试前运行的任务(如编译)
            "miDebuggerPath": "/usr/bin/gdb",  // GDB 的路径
            "internalConsoleOptions": "neverOpen"
        }
    ]
}
创建 tasks.json

如果你希望在调试前自动编译程序,可以在 .vscode 文件夹中创建 tasks.json 文件,定义编译任务。

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "type": "shell",
            "command": "g++",
            "args": [
                "-g",
                "-o",
                "${workspaceFolder}/my_program",
                "${workspaceFolder}/main.cpp"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": ["$gcc"],
            "detail": "Generated task to build the program."
        }
    ]
}
启动调试
  1. 打开 VSCode。
  2. 点击左侧活动栏中的“运行和调试”图标(通常是一个虫子图标)。
  3. 选择你刚刚配置的调试配置(例如 (gdb) Launch)。
  4. 点击绿色的“开始调试”按钮,或者按 F5

3. 使用 LLDB

LLDB 是另一个强大的调试器,最初为 macOS 设计,但现在也广泛支持 Linux。它的命令语法与 GDB 类似,但有一些差异。

安装 LLDB
  • Debian/Ubuntu:

    sudo apt-get install lldb
    
  • Fedora/CentOS/RHEL:

    sudo dnf install lldb
    
  • Arch Linux:

    sudo pacman -S lldb
    
启动 LLDB
lldb ./my_program
常用 LLDB 命令
  • run [args]: 开始运行程序,传递参数(如果有)。

    (lldb) run arg1 arg2
    
  • breakpoint set -n <function>breakpoint set -f <file> -l <line>: 设置断点。

    (lldb) breakpoint set -n main
    (lldb) breakpoint set -f my_file.cpp -l 10
    
  • continuec: 继续执行程序,直到遇到下一个断点或异常。

    (lldb) continue
    
  • steps: 单步执行,进入函数内部。

    (lldb) step
    
  • nextn: 单步执行,不进入函数内部。

    (lldb) next
    
  • print <expression>p <expression>: 打印变量或表达式的值。

    (lldb) print x
    (lldb) print my_object->get_value()
    
  • thread backtracebt: 显示当前调用栈。

    (lldb) thread backtrace
    
  • frame variable: 显示当前帧中的变量。

    (lldb) frame variable
    
  • quitq: 退出 LLDB。

    (lldb) quit
    

4. 使用 Valgrind 检查内存问题

Valgrind 是一个非常有用的工具,专门用于检测内存泄漏、非法内存访问等问题。虽然它不是调试器,但它可以帮助你发现潜在的内存问题。

安装 Valgrind
  • Debian/Ubuntu:

    sudo apt-get install valgrind
    
  • Fedora/CentOS/RHEL:

    sudo dnf install valgrind
    
  • Arch Linux:

    sudo pacman -S valgrind
    
使用 Valgrind
valgrind --leak-check=full ./my_program

Valgrind 会运行你的程序,并在程序结束时输出详细的内存分析报告。你可以根据报告中的提示修复内存泄漏或其他问题。

5. 使用 AddressSanitizer (ASan) 检测内存错误

AddressSanitizer 是一个编译器内置的工具,专门用于检测内存错误,如越界访问、未初始化内存访问等。它比 Valgrind 更快,因为它是在编译时插入检查代码的。

编译时启用 ASan
g++ -fsanitize=address -g -o my_program my_program.cpp
运行程序
./my_program

如果程序中有内存错误,AddressSanitizer 会在运行时输出详细的错误信息。

6. 使用 GProf 分析性能

GProf 是一个简单的性能分析工具,可以帮助你了解程序的性能瓶颈。它通过记录函数调用的时间和频率来生成性能报告。

编译时启用 GProf
g++ -pg -o my_program my_program.cpp
运行程序
./my_program

程序运行后会生成一个名为 gmon.out 的文件,包含性能数据。

生成报告
gprof ./my_program gmon.out > profile.txt

你可以查看 profile.txt 文件,了解哪些函数消耗了最多的时间。

总结

在 Linux 上调试 C++ 程序有多种工具和方法可供选择,具体取决于你的需求:

  • GDB 是最常用的调试器,适合大多数调试场景。
  • VSCode 提供了图形化的调试界面,结合 GDB 或 LLDB,适合喜欢图形化工具的开发者。
  • LLDB 是另一个强大的调试器,尤其适合 macOS 和现代 Linux 系统。
  • ValgrindAddressSanitizer 专注于内存问题的检测,帮助你发现潜在的内存泄漏和非法访问。
  • GProf 用于性能分析,帮助你优化程序的性能。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ansible-api分析(VariableManager变量)

一. 简述&#xff1a; ansible是一个非常强大的工具&#xff0c;可以支持多种类型(字符,数字,列表&#xff0c;字典等)的变量。除了有大量的内置变量及fact变量&#xff0c;也可以通过多种方式进行变量自定义 。不同方式定义的变量&#xff0c;优先级也不太一样&#xff0c;之…

2025年PMP考试最新报名通知

经PMI和中国国际人才交流基金会研究决定&#xff0c;中国大陆地区2025年第一期PMI认证考试定于3月15日举办。在基金会网站报名参加本次PMI认证考试的考生须认真阅读下文&#xff0c;知悉考试安排及注意事项&#xff0c;并遵守考试有关规定。 一、时间安排 &#xff08;一&#…

Mysql--基础篇--数据类型(整数,浮点数,日期,枚举,二进制,空间类型等)

MySQL提供了多种数据类型&#xff0c;用于定义表中列的数据格式。选择合适的数据类型不仅可以提高查询性能&#xff0c;还能确保数据的完整性和准确性。 一、数值类型 数值类型用于存储整数、浮点数和定点数。根据精度和范围的不同&#xff0c;数值类型可以分为以下几类&…

1-Transformer算法解读

目录 一.RNN与Transfrmer 二.word2vec 三.自注意力机制 四.辅助向量Q/K/V 五.计算过程 六.整体架构​编辑 七.Bert 一.RNN与Transfrmer RNN(循环神经网络)和Transformer都是深度学习中用于处理序列数据的模型,但它们在结构和性能上有显著的区别。以下是它们的一些…

Java Web开发进阶——Spring Boot与Spring Data JPA

Spring Data JPA 是 Spring 提供的一种面向数据访问的持久化框架&#xff0c;它简化了 JPA 的实现&#xff0c;为开发者提供了一种快速操作数据库的方式。在结合 Spring Boot 使用时&#xff0c;开发者能够快速完成数据库访问层的开发。 1. 介绍Spring Data JPA 1.1 什么是Spr…

【计算机操作系统:一、绪论】

第1章 绪论 1.1 操作系统在计算机系统中的地位 1.1.1 存储程序式计算机的结构和特点 存储程序式计算机&#xff08;Stored Program Computer&#xff09;是现代计算机的基础&#xff0c;其概念源于冯诺依曼&#xff08;John von Neumann&#xff09;提出的模型。这种计算机架…

如何查看服务器上的MySQL/Redis等系统服务状态和列表

如果呢你知道系统服务名称&#xff0c;要看状态很简单&#xff1a; systemctl status server-name 比如 systemctl status nginxsystemctl status redis # 等 这是一个nginx的示例&#xff1a; 那问题是 当你不知道服务名称时该怎么办。举个例子&#xff0c;比如mysql在启动…

安科瑞Acrel-1000DP分布式光伏监控系统在浙江安吉成3234.465kWp分布式光伏发电项目中的应用

摘 要&#xff1a;分布式光伏发电站是指将光伏发电组件安装在用户的建筑物屋顶、空地或其他适合的场地上&#xff0c;利用太阳能进行发电的一种可再生能源利用方式&#xff0c;与传统的大型集中式光伏电站相比&#xff0c;分布式光伏发电具有更灵活的布局、更低的建设成本和更高…

探索 Vue.js 的动态样式与交互:一个有趣的样式调整应用

修改日期备注2025.1.3初版 一、前言 今天和大家分享在 Vue.js 学习过程中开发的超酷的小应用。这个应用可以让我们通过一些简单的交互元素&#xff0c;如复选框、下拉菜单和输入框&#xff0c;来动态地改变页面上元素的样式哦 让我们一起深入了解一下这个项目的实现过程&…

大数据-268 实时数仓 - ODS层 将 Kafka 中的维度表写入 DIM

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇开始了&#xff01; MyBatis 更新完毕目前开始更新 Spring&#xff0c;一起深入浅出&#xff01; 目前已经更新到了&#xff1a; H…

把vue项目或者vue组件发布成npm包或者打包成lib库文件本地使用

将vue项目发布成npm库文件&#xff0c;第三方通过npm依赖安装使用&#xff1b;使用最近公司接了一个项目&#xff0c;这个项目需要集成到第三方页面&#xff0c;在第三方页面点击项目名称&#xff0c;页面变成我们的项目页面&#xff1b;要求以npm库文件提供给他们&#xff1b;…

Kafka为什么要放弃Zookeeper

1.Kafka简介 Apache Kafka最早是由Linkedin公司开发&#xff0c;后来捐献给了Apack基金会。 Kafka被官方定义为分布式流式处理平台&#xff0c;因为具备高吞吐、可持久化、可水平扩展等特性而被广泛使用。目前Kafka具体如下功能&#xff1a; 消息队列,Kafka具有系统解耦、流…

【JVM】总结篇-类的加载篇之 类的加载器 和ClassLoader分析

文章目录 类的加载器ClassLoader自定义类加载器双亲委派机制概念源码分析优势劣势如何打破Tomcat 沙箱安全机制JDK9 双亲委派机制变化 类的加载器 获得当前类的ClassLoader clazz.getClassLoader() 获得当前线程上下文的ClassLoader Thread.currentThread().getContextClassLoa…

java 转义 反斜杠 Unexpected internal error near index 1

代码&#xff1a; String str"a\\c"; //出现异常&#xff0c;Unexpected internal error near index 1 //System.out.println(str.replaceAll("\\", "c"));//以下三种都正确 System.out.println(str.replace(\\, c)); System.out.println(str.r…

el-table 实现纵向多级表头

为了实现上图效果&#xff0c;最开始打算用el-row、el-col去实现&#xff0c;但发现把表头和数据分成两大列时&#xff0c;数据太多时会导致所在格高度变高。但由于每一格数据肯定不一样&#xff0c;为保持高度样式一致&#xff0c;就需要我们手动去获取最高格的高度之后再设置…

2025最新版Visual Studio Code安装使用指南

2025最新版Visual Studio Code安装使用指南 Installation and Usage Guide for the Latest Visual Studio Code in 2024 By JacksonML 2025-1-7 1. Visual Studio Code背景 早在二十年前&#xff0c;通用的集成开发环境&#xff08;Integrated Deveopment Environment, 简称…

Flutter 鸿蒙化 flutter和鸿蒙next混和渲染

前言导读 这一个节课我们讲一下PlatformView的是使用 我们在实战中有可能出现了在鸿蒙next只加载一部分Flutter的情况 我们今天就讲一下这种情况具体实现要使用到我们的PlatformView 效果图 具体实现: 一、Native侧 使用 DevEco Studio工具打开 platform_view_example\oho…

LabVIEW语言学习过程是什么?

学习LabVIEW语言的过程可以分为几个阶段&#xff0c;每个阶段的重点内容逐步加深&#xff0c;帮助你从入门到精通。以下是一个简洁的学习过程&#xff1a; ​ 1. 基础入门阶段 理解图形化编程&#xff1a;LabVIEW是一种图形化编程语言&#xff0c;与传统的文本编程语言不同&am…

Kubernetes Gateway API-4-TCPRoute和GRPCRoute

1 TCPRoute 目前 TCP routing 还处于实验阶段。 Gateway API 被设计为与多个协议一起工作&#xff0c;TCPRoute 就是这样一个允许管理TCP流量的路由。 在这个例子中&#xff0c;我们有一个 Gateway 资源和两个 TCPRoute 资源&#xff0c;它们按照以下规则分配流量&#xff1…

嵌入式SD/TF卡通用协议-SDIO协议

SD卡&#xff08;SecureDigital MemoryCard&#xff09;即&#xff1a;安全数码卡&#xff0c;它是在MMC的基础上发展而来&#xff0c;是一种基于半导体快闪记忆器的新一代记忆设备&#xff0c;它被广泛地于便携式装置上使用&#xff0c;例如数码相机、个人数码助理(PDA)和多媒…