文章目录
- 1. 可执行程序的Debug版和Release版区别
- 一、编译选项与目的
- 二、性能与体积
- 三、功能与特性
- 四、查看可执行文件
- 2. GDB 相关命令
- GDB常用命令
1. 可执行程序的Debug版和Release版区别
一、编译选项与目的
-
Debug版:
- 编译选项:通常使用包含调试信息的编译选项,如/MDd、/MLd或/MTd,并关闭优化。
- 目的:主要用于开发和调试阶段,提供强大的调试功能,帮助开发者查找和修复程序中的错误。
-
Release版:
- 编译选项:使用生成性能更优、体积更小的可执行文件的编译选项,如/MD、/ML或/MT,并开启优化(如/O1或/O2)。
- 目的:用于最终用户使用,关注程序的性能和稳定性,不包含调试信息,无法进行调试。
二、性能与体积
-
Debug版:
- 性能:由于关闭了优化,生成的可执行文件通常体积较大,运行速度较慢。
- 体积:包含详细的调试信息,使得文件体积相对较大。
-
Release版:
- 性能:进行了各种优化,生成的可执行文件体积小,运行速度快。
- 体积:不包含调试信息,因此体积更小。
三、功能与特性
-
Debug版:
- 功能:保留所有功能,包括开发过程中用来测试的功能。
- 特性:包含额外的调试信息,如符号表、行号和代码的其他元数据,以帮助开发者在调试时更容易地追踪代码执行。此外,还支持编辑继续和内存错误捕获等功能。
-
Release版:
- 功能:可能省略某些调试用的功能,以提升安全性和性能。
- 特性:不包含调试信息,无法进行调试操作。但提供了经过优化的代码,以提高程序的运行效率。
四、查看可执行文件
readelf -S gdbtest-Debug (可执行程序名)
其中带有调试信息
2. GDB 相关命令
您列出的是GDB(GNU Debugger)的一些常用命令和功能描述,但有一些小错误和不准确之处。下面我将对这些命令进行修正和补充,以便您更好地理解和使用GDB进行程序调试。
所使用案例的源代码如下
#include <iostream>
class Calculator {
public:
// 加法
double add(double a, double b) {
return a + b;
}
// 减法
double subtract(double a, double b) {
return a - b;
}
// 乘法
double multiply(double a, double b) {
return a * b;
}
// 除法
double divide(double a, double b) {
if (b == 0) {
std::cerr << "Error: Division by zero!" << std::endl;
throw std::runtime_error("Division by zero");
}
return a / b;
}
};
int main() {
Calculator calc;
double num1, num2;
char operation;
std::cout << "Enter first number: ";
std::cin >> num1;
std::cout << "Enter an operator (+, -, *, /): ";
std::cin >> operation;
std::cout << "Enter second number: ";
std::cin >> num2;
try {
switch (operation) {
case '+':
std::cout << num1 << " + " << num2 << " = " << calc.add(num1, num2) << std::endl;
break;
case '-':
std::cout << num1 << " - " << num2 << " = " << calc.subtract(num1, num2) << std::endl;
break;
case '*':
std::cout << num1 << " * " << num2 << " = " << calc.multiply(num1, num2) << std::endl;
break;
case '/':
std::cout << num1 << " / " << num2 << " = " << calc.divide(num1, num2) << std::endl;
break;
default:
std::cerr << "Error: Unsupported operator!" << std::endl;
break;
}
} catch (const std::runtime_error& e) {
std::cerr << e.what() << std::endl;
}
return 0;
}
GDB常用命令
- 启动GDB
- gdb + 可执行程序名
-
运行程序
run
或r
[参数]:运行程序,可以传递可选的命令行参数。
-
显示源代码
list
或l
[行号/函数名]:显示源代码。如果指定行号,则显示该行附近的代码;如果指定函数名,则显示该函数的源代码。list
或l
:如果之前已经使用过list
命令,则继续显示接下来的代码,每次默认显示10行。
-
单步执行
next
或n
:执行下一行代码,但不进入函数内部(即跳过函数调用)。step
或s
:执行下一行代码,如果遇到函数调用,则进入函数内部。
-
设置断点
break
或b
[行号/函数名]:在指定行或函数开头设置断点。
-
查看断点信息
info breakpoints
或i b
:查看当前设置的所有断点信息。
-
删除断点
delete breakpoints
:这个命令是不准确的,应该是delete
[断点号] 或d
[断点号] 来删除指定的断点。delete
或d
:如果不跟断点号,则默认删除所有断点(但某些GDB版本可能不支持这种用法,通常需要明确指定断点号)。
-
执行到函数返回
finish
:继续执行程序,直到当前函数返回,然后停下来等待命令。
-
打印表达式的值
print
或p
[表达式]:打印表达式的值。通过表达式可以修改变量的值(但通常不推荐在调试过程中直接修改变量值,因为这可能会掩盖程序中的真实问题)。print
或p
[变量名]:打印变量的值。
-
修改变量的值
set var
[变量名] = [新值]:修改变量的值。
- 连续执行
- continue 或 c:从当前位置开始连续执行程序,直到遇到下一个断点或程序结束
-
禁用/启用断点
disable
[断点号]:禁用指定的断点。enable
[断点号]:启用指定的断点。
-
跟踪查看变量
-
display
[变量名]:每次程序停下来时都显示指定变量的值。
-
undisplay
[编号]:取消之前通过display
设置的跟踪。
-
-
跳转到指定行
until
[行号]:执行程序直到到达指定行(但通常不用于设置断点或改变执行流程,而是用于查看执行到某点时的状态)。
-
查看函数调用栈
backtrace
或bt
:查看当前函数的调用栈及参数。
-
查看局部变量
info locals
或i locals
:查看当前栈帧中局部变量的值。
-
退出GDB
quit
:退出GDB调试器。