0 c linux assembly gdb pointers
我目前正在尝试从一本名为“剥削的艺术”的书中学习低级编程。这本书在编写了一些代码之后,用 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);
...
Run Code Online (Sandbox Code Playgroud)
在 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 位整数(via x/xw)时,前 4 个字节被解释为整数。假设您的机器使用小端内存顺序,则将其作为值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
Run Code Online (Sandbox Code Playgroud)