c - 使用 gdb 检查指针时返回的第二个十六进制数是多少?
问题描述
我目前正在尝试从一本名为“剥削的艺术”的书中学习低级编程。这本书在编写了一些代码后,用 gdb 对其进行了检查。我现在在关于指针的部分。
我现在的代码是这样的:
#include <string.h>
int main(){
char str_a[20]; //20 charachters array
char *pointer;
char *pointer2;
strcpy(str_a, "hello world\n");
pointer = str_a; //set pointer to the start of the array
printf("%s\n", pointer);
pointer2 = pointer + 2;
printf(pointer2);
strcpy(pointer2, "y you guys\n");
printf("%s\n", pointer);
...
在 gdb 中,我中断了行printf("%s\n", pointer);
。
*pointer
然后我使用命令检查指针x/xw pointer
,它返回0x7fffffffde20: 0x6c6c6568
。我知道这0x7fffffffde20
是指针指向的内存,但我不明白是什么0x6c6c6568
。
然后我用x/xw &pointer
直接看内存*pointer
所在的位置,这次又返回了0x7fffffffde10: 0xffffde20
。我一直不明白第二个十六进制是什么。
如果我尝试使用x/xw 0xffffde20
它返回的命令来检查它
0xffffde20: Cannot access memory at address 0xffffde20
有人可以帮助我吗?
解决方案
然后我使用命令检查指针 *pointer
x/xw pointer
,它返回
0x7fffffffde20: 0x6c6c6568
.我知道这是指向
0x7fffffffde20
的记忆pointer
,但我不明白是什么0x6c6c6568
。
调试器只是向您显示一个地址和存储在该地址的内容。
在您的代码pointer
指向您的数组中,您在其中复制了字符串"hello world\n"
在内存中这是(十六进制)
68 65 6C 6C 6F 20 77 6F 72 6C 64 0A
当您读取为 32 位整数(通过x/xw
)时,前 4 个字节被解释为整数。假设您的机器使用 little endian 内存顺序,则将其作为 value 0x6c6c6586
。如果您在下一个地址再次读取,您将获得 和 的整数"o wo"
表示"rld\n"
。
然后我用
x/xw &pointer
直接看内存*pointer
所在的位置,这次又返回了
0x7fffffffde10: 0xffffde20
我一直不明白第二个十六进制是什么。
同样,您会得到一个地址和一些内容。内容的类型/大小由您用来阅读它的命令定义。您读取 32 位并从该地址获得 32 位。
我们在这里期待什么结果?
pointer
在前面的命令中,您在指向的地址处读取内存。这次你在pointer
它自己所在的地址读取内存。
请记住:第一个命令显示 address 0x7fffffffde20
。您现在看到的是,pointer
变量存储在0x7fffffffde10
,前 32 位是0xffffde20
. 请注意,这类似于在第一次读取命令中被视为地址的值。
这意味着,0xffffde20
只是0x7fffffffde20
缺少另一半的一半。您只是没有阅读足够的内容来展示它们。
正如@jester 在评论中提到的,您应该使用x/xa
来显示地址。
如果我尝试使用
x/xw 0xffffde20
它返回的命令来检查它
0xffffde20: Cannot access memory at address 0xffffde20
有了上面的发现,这并不奇怪。您只提供了部分地址,这会导致无效的内存访问。
从数字来看,您的内存布局和内容与此类似:
0x7fffffffde30 still str_a xx xx xx xx
0x7fffffffde28 still str_a 72 6C 64 0A 00 xx xx xx
0x7fffffffde20 char str_a[20] 68 65 6C 6C 6F 20 77 6F
0x7fffffffde18 ...
0x7fffffffde10 char *pointer 0x7fffffffde20 == address of str_a
0x7fffffffde08 char *pointer2