编译命令gcc -g -omain memlook.c然后运行gbd ./main进入调试。

(gdb) list 15
10        }
11        i = 0;
12        for (; i < 10; i++)
13        {
14            printf("%d ",p[i]);
15        }
16        free(p);
17        return 0;
18
19    }
在free(p)处设置断点break 16

(gdb) break 16
Breakpoint 1 at 0x74e: file memlook.c, line 16.
然后运行

(gdb) run
Starting program: /mnt/hgfs/linux/cpp/gdblearn/main

Breakpoint 1, main () at memlook.c:16
16        free(p);
接下来查看指针p指向的数据

方式一:
当需要查看一段连续内存空间的值的时间,可以使用GDB的“@”操作符,“@”的左边是第一个内存地址,“@”的右边则是想查看内存的长度。

int *array = (int *) malloc (len * sizeof (int));

在GDB调试过程中这样显示出这个动态数组的值:

p *array@len

(gdb) print *p@10
$1 = "\000\001\002\003\004\005\006\a\b\t"
(gdb) print *(char*)p@10
$2 = "\000\001\002\003\004\005\006\a\b\t"
(gdb) print *(int*)p@10
$3 = {50462976, 117835012, 2312, 0, 0, 0, 1041, 0, 540090416, 540221490}
(gdb)

我们可以使用examine命令(缩写为x)来查看内存地址中的值。examine命令的语法如下所示:

x/<n/f/u> <addr>

<addr>表示一个内存地址。“x/”后的n、f、u都是可选的参数,n 是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容;f 表示显示的格式,如果地址所指的是字符串,那么格式可以是s,如果地址是指令地址,那么格式可以是i;u 表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4字节。u参数可以被一些字符代替:b表示单字节,h表示双字节,w表示四字节,g表示八字节。当我们指定了字节长度后,GDB会从指定的内存地址开始,读写指定字节,并把其当作一个值取出来。n、f、u这3个参数可以一起使用,例如命令“x/3uh 0x54320”表示从内存地址0x54320开始以双字节为1个单位(h)、16进制方式(u)显示3个单位(3)的内存。

print的输出格式包括:

x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。

示例如下:

(gdb) x/10db p
0x555555756260:    0    1    2    3    4    5    6    7
0x555555756268:    8    9
(gdb) x/10dh p
0x555555756260:    256    770    1284    1798    2312    0    0    0
0x555555756270:    0    0
(gdb)

x/10db p 表示查看p指针指向的内存中往后10个地址的数据,并以十进制格式显示变量,以单字节读写指定字节。

(gdb) print *(int*)p
$5 = 50462976
*(int*)p表示将按照整型指针处理。

更多案例:

main()
{
char *c = "hello world";
printf("%s\n", c);
}

char *c = "hello world";

下一行设置断点后:

(gdb) l
1    main()
2    {
3        char *c = "hello world";
4        printf("%s\n", c);
5    }
(gdb) b 4
Breakpoint 1 at 0x100000f17: file main.c, line 4.
(gdb) r
Starting program: /Users/songbarry/main
Reading symbols for shared libraries +. done

Breakpoint 1, main () at main.c:4
4        printf("%s\n", c);

可以通过多种方式看C指向的字符串:

(gdb) p c
$1 = 0x100000f2e "hello world"

(gdb) x/s 0x100000f2e
0x100000f2e:     "hello world"

(gdb) p (char *)0x100000f2e
$3 = 0x100000f2e "hello world"

将第一个字符改为大写:

(gdb) p *(char *)0x100000f2e='H'
$4 = 72 'H'

再看看C:

(gdb) p c
$5 = 0x100000f2e "Hello world"

run | r : 运行程序,当遇到断点的时候,程序会在断点处停止运行,等待用户输入下一步的命令。 start :运行,从第一条语句开始 continue | c:继续执行,直到下一个断点处(或运行结束)。 step | s :执行下一句,如果下一执行语句为函数,进入函数 next | n | 换行 :执行下一句,不进入函数 0x01:毕竟学Linux就要学会 gdb 调试C语言啦,这里我们来看看 指针 在内存里到底是长什么样子的,毕竟眼见为实,不多说来调试看看吧; 0x02:代码如下所示 #include <stdio.h> int main() char a = 'c'; char *p = &a; char **ptr = &p; return 0; gcc -g -o test test.c --> 生成调试文件 之前有介绍过如何使用 gdb 查看 当前 指针 具体属于哪个派生类以及派生类的具体 内容 gdb 查看 指针 内容 ),那么对于复杂项目的调试,配合VsCode的断点和单步调试功能(VsCode单步调试),如果能够实时 查看 当前 指针 指向 的所有内存信息,将大大提升debug的效率,本节将介绍如何实现。 软件是人思维的产物。智者千虑,必有一失,人的思维总有缺陷,反映到软件层面上就是程序 bug。程序 bug 的终极体现就是core dump,core dump 是软件错误无法恢复的产物。 我们经常见到的bug说“闪退、意外终止等”,这里说的大部分是指对应程序由于各种异常或者bug导致在运行过程中异常退出或者中止,并且在满足一定条件下(这里为什么说需要满足一定的条件呢?下面会分析)会产生一个叫做corefile的文件。 通常情况下,corefile文件会包含了程序运行时的内存,寄存器状态,堆栈 指针 ,内存管理信息还有各种函数调用堆栈信息等,我们可以理解为是程序工作当前状态存储生成的一个文件,许多的程序出错的时候都会产生一个corefile文件,通过工具分析这个文件,我们可以定位到程序异常退出的时候对应的堆栈调用等信息,找出问题所在并进行及时解决。 对于那些具有高级编程语言诸如: Ruby、Scheme、Haskell 等背景的人来说,学习 C 语言是具有挑战性的。除了纠结于 C  语言中像手动内存管理和 指针 等底层特性外,你必须在没有 REPL ( Read-Eval-Print Loop ) 的条件下完成工作。一旦你已经习惯于在 REPL 环境下进行探索性的编程,必须进行“编写-编译-运行”这样循环实在有点令人生厌。 最近我发现其实可以用 GDB 来作为 C 语言的伪 REPL。我一直尝试使用 GDB 作为学习 C 语言的工具,而不仅仅是用来调试 C 程序,事实上这非常有趣。 这篇文章我的目的就是向你展示 GDB 是一个非常好的学习 C 网易云课堂免费课程:《C++跨平台开发中的编译错误》 --------------------------------------------------------------------------- 在C++中提供了this 指针 来访问对象自身。那么,在开发的时候我们一般会在什么情况下会用到this 指针 呢? 一种...