gdb调试工具
熟练地掌握gdb调试工具是十分重要的,能够帮助我们加深对代码及相关概念的理解。部分指令如下:
| 指令 | 功能 |
|---|---|
| l(list) | 列出源代码 |
| start | 进行单行调试 |
| p | 打印某值 |
| n | 继续执行下一行 |
| s | 进入函数内部 |
| bt | 查看函数堆栈 |
| 回车 | 继续刚才的命令 |
| x/(数字)(类型)+地址 | 输出内存中的值,例如x/3d+地址 |
| f +函数号 | 可查看当前函数中的变量值 |
内存管理
- 32位操作系统只能使用4G内存,地址总线32位(寻址空间32位)
- 64位操作系统,内存相比较32位足够多了。
其中,用户应用程序使用48位足够用(0x7fffffffffff);剩余的用于操作系统内核。
| 内存规划(这里只表示顺序,未体现大小) |
|---|
| 系统内核 |
| 自由可分配 |
| 堆 |
| 数据段 |
| 代码段 |
几点解释:
- C语言语法不允许直接操作代码段
- 栈能够把程序执行过程中的全部状态记录下来,地址比较大;此外遵循先进后出原则,先进的地址大,后进的地址小。
- 操作系统和应用程序隔离开的好处:操作系统不会大量占用,避免机器卡住等等
指针
- 如果说变量只是一个代号,本质是内存。而指针保存的就是内存地址。
- 指针偏移运算,根据对应数据类型占几个字节(如在64位操作系统中,指针占8个字节,整型占4个字节)
- 数组本质也是指针类型,是指针常量
最开始可以通过调试简单的代码来更深入地理解指针和内存的内涵,如下面的简单例程。我们可以在gdb条件下,通过p &函数名;p &变量名;p *变量名等来查看内存地址或者存放数据等的信息。
#include <stdio.h>
int global=0;
int rect(int a, int b)
{
static int count=0;
count++;
global++;
int s=a*b;
return s;
}
int quadrate(int a)
{
static int count=0;
count++;
global++;
int s=rect(a,a);
return s;
}
int main()
{
int a=3;
int b=4;
int *pa=&a;
int *pb=&b;
int *pglobal=&global;
int (*pquadrate)(int a)=&quadrate;
//int s=quadrate(a);
int s=(*pquadrate)(a);
printf("%d\n",s);
}
本文详细介绍GDB调试工具的使用方法,包括源代码显示、单行调试、值打印等功能,以及如何通过GDB理解内存管理,如32位与64位操作系统内存差异、内存规划、指针操作及数组本质。
352

被折叠的 条评论
为什么被折叠?



