gdb 无法访问内存地址错误
gdb can't access memory address error
这是我的故障代码:
0x0804844d <+0>: push %ebp
0x0804844e <+1>: mov %esp,%ebp
0x08048450 <+3>: and [=10=]xfffffff0,%esp
0x08048453 <+6>: sub [=10=]x20,%esp
0x08048456 <+9>: movl [=10=]x8048540,(%esp)
0x0804845d <+16>: call 0x8048310 <puts@plt>
0x08048462 <+21>: lea 0x1c(%esp),%eax
0x08048466 <+25>: mov %eax,0x4(%esp)
0x0804846a <+29>: movl [=10=]x8048555,(%esp)
0x08048471 <+36>: call 0x8048320 <scanf@plt>
0x08048476 <+41>: mov 0x1c(%esp),%eax
0x0804847a <+45>: cmp [=10=]x208c,%eax
0x0804847f <+50>: jne 0x804848f <main+66>
0x08048481 <+52>: movl [=10=]x8048558,(%esp)
0x08048488 <+59>: call 0x8048310 <puts@plt>
0x0804848d <+64>: jmp 0x804849b <main+78>
=> 0x0804848f <+66>: movl [=10=]x8048569,(%esp)
0x08048496 <+73>: call 0x8048310 <puts@plt>
0x0804849b <+78>: mov [=10=]x0,%eax
0x080484a0 <+83>: leave
0x080484a1 <+84>: ret
我要检查的是 $0x208c。当我键入 x/xw 0x208c 时,它返回错误,提示无法访问地址 0x208c 处的内存。当我键入 Info registers 并查看 eax 时,它会显示我提供的值。所以基本上这个程序比较两个值,并根据它打印一些东西 out.The 问题是这是大学的作业,我没有代码。希望你能帮忙。谢谢。
When I type x/xw 0x208c
it gives me back error which says Cannot access memory at address 0x208c
你的程序的反汇编表明它做了这样的事情:
puts("some string");
int i;
scanf("%d", &i); // I don't know what the actual format string is.
// You can find out with x/s 0x8048555
if (i == 0x208c) { ... } else { ... }
换句话说,0x208c
是您的程序在其中硬编码的值 (8332
),并且 不是 指针.因此,GDB 完全正确地告诉您,如果您将 0x208c
解释为指针,则该指针不指向可读内存。
i finally figured out to use print statement instead of x/xw
您似乎不明白 print
和 examine
命令之间的区别。考虑这个例子:
int foo = 42;
int *pfoo = &foo;
在上面,print pfoo
会给你 foo
的 地址 ,而 x pfoo
会给你 value 存储在该地址(即 foo
的值)。
我发现无法检查没有 PROT_READ
标志的 mmap
ed 内存。这不是OP的问题,是我的问题,报错也是一样
而不是
mmap(0, size, PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
做
mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
瞧,可以检查内存了。
未初始化的指针
回想起来这很明显,但这就是导致 GDB 向我显示该错误消息的原因。沿着:
#include <stdio.h>
int main(void) {
int *p;
printf("*p = %d\n", *p);
}
然后:
gdb -q -nh -ex run ./tmp.out
Reading symbols from ./tmp.out...done.
Starting program: /home/ciro/bak/git/cpp-cheat/gdb/tmp.out
Program received signal SIGSEGV, Segmentation fault.
0x0000555555554656 in main () at tmp.c:5
5 printf("*p = %d\n", *p);
(gdb) print *p
Cannot access memory at address 0x0
但当然是在一个复杂的程序中,地址是随机的,不同于零。
在我的例子中,问题是由调用长度大于 mmap 的 munmap 引起的:
#include <errno.h>
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
int main(){
size_t length_alloc = 10354688;
size_t length_unmap = 5917171456;
void *v = mmap(0, 10354688, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (v == MAP_FAILED) {
printf("mmap of %lu bytes failed with error: %s", 10354688, strerror(errno));
}else{
printf("mmaped %p\n", v);
munmap(v, length_unmap);
}
}
所以取消映射也取消映射几个线程的堆栈。相当讨厌的一个,因为它使核心转储无法以我当前的技能水平使用。特别是在原始问题中,传递给 munmap 的大小有些随机。它只是有时会崩溃,并且会在一个非常漫长的过程结束时崩溃。
如果GDB 提示未找到内存地址,则表示该符号在gdb 打开的可执行文件或通过文件exefilename 打开的文件中不可用。或者您没有使用 -g 选项编译 exefile。当您是 gdb 的新手时会发生什么,您可能已经给出了命令文件 argfile 而不是 运行 argfile。请检查。
我遇到了同样的错误。我通过使用 Gparted 软件增加交换 space 解决了我的问题。
1- 首先使用 "sudo apt-get install gparted" 安装 Gparted
2- 打开 Gparted 并右键单击交换然后 select Resize/Move
(注意:只有在交换内存之前或之后有未分配的内存时,您才能增加交换大小)
这是我的故障代码:
0x0804844d <+0>: push %ebp
0x0804844e <+1>: mov %esp,%ebp
0x08048450 <+3>: and [=10=]xfffffff0,%esp
0x08048453 <+6>: sub [=10=]x20,%esp
0x08048456 <+9>: movl [=10=]x8048540,(%esp)
0x0804845d <+16>: call 0x8048310 <puts@plt>
0x08048462 <+21>: lea 0x1c(%esp),%eax
0x08048466 <+25>: mov %eax,0x4(%esp)
0x0804846a <+29>: movl [=10=]x8048555,(%esp)
0x08048471 <+36>: call 0x8048320 <scanf@plt>
0x08048476 <+41>: mov 0x1c(%esp),%eax
0x0804847a <+45>: cmp [=10=]x208c,%eax
0x0804847f <+50>: jne 0x804848f <main+66>
0x08048481 <+52>: movl [=10=]x8048558,(%esp)
0x08048488 <+59>: call 0x8048310 <puts@plt>
0x0804848d <+64>: jmp 0x804849b <main+78>
=> 0x0804848f <+66>: movl [=10=]x8048569,(%esp)
0x08048496 <+73>: call 0x8048310 <puts@plt>
0x0804849b <+78>: mov [=10=]x0,%eax
0x080484a0 <+83>: leave
0x080484a1 <+84>: ret
我要检查的是 $0x208c。当我键入 x/xw 0x208c 时,它返回错误,提示无法访问地址 0x208c 处的内存。当我键入 Info registers 并查看 eax 时,它会显示我提供的值。所以基本上这个程序比较两个值,并根据它打印一些东西 out.The 问题是这是大学的作业,我没有代码。希望你能帮忙。谢谢。
When I type
x/xw 0x208c
it gives me back error which saysCannot access memory at address 0x208c
你的程序的反汇编表明它做了这样的事情:
puts("some string");
int i;
scanf("%d", &i); // I don't know what the actual format string is.
// You can find out with x/s 0x8048555
if (i == 0x208c) { ... } else { ... }
换句话说,0x208c
是您的程序在其中硬编码的值 (8332
),并且 不是 指针.因此,GDB 完全正确地告诉您,如果您将 0x208c
解释为指针,则该指针不指向可读内存。
i finally figured out to use print statement instead of x/xw
您似乎不明白 print
和 examine
命令之间的区别。考虑这个例子:
int foo = 42;
int *pfoo = &foo;
在上面,print pfoo
会给你 foo
的 地址 ,而 x pfoo
会给你 value 存储在该地址(即 foo
的值)。
我发现无法检查没有 PROT_READ
标志的 mmap
ed 内存。这不是OP的问题,是我的问题,报错也是一样
而不是
mmap(0, size, PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
做
mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
瞧,可以检查内存了。
未初始化的指针
回想起来这很明显,但这就是导致 GDB 向我显示该错误消息的原因。沿着:
#include <stdio.h>
int main(void) {
int *p;
printf("*p = %d\n", *p);
}
然后:
gdb -q -nh -ex run ./tmp.out
Reading symbols from ./tmp.out...done.
Starting program: /home/ciro/bak/git/cpp-cheat/gdb/tmp.out
Program received signal SIGSEGV, Segmentation fault.
0x0000555555554656 in main () at tmp.c:5
5 printf("*p = %d\n", *p);
(gdb) print *p
Cannot access memory at address 0x0
但当然是在一个复杂的程序中,地址是随机的,不同于零。
在我的例子中,问题是由调用长度大于 mmap 的 munmap 引起的:
#include <errno.h>
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
int main(){
size_t length_alloc = 10354688;
size_t length_unmap = 5917171456;
void *v = mmap(0, 10354688, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (v == MAP_FAILED) {
printf("mmap of %lu bytes failed with error: %s", 10354688, strerror(errno));
}else{
printf("mmaped %p\n", v);
munmap(v, length_unmap);
}
}
所以取消映射也取消映射几个线程的堆栈。相当讨厌的一个,因为它使核心转储无法以我当前的技能水平使用。特别是在原始问题中,传递给 munmap 的大小有些随机。它只是有时会崩溃,并且会在一个非常漫长的过程结束时崩溃。
如果GDB 提示未找到内存地址,则表示该符号在gdb 打开的可执行文件或通过文件exefilename 打开的文件中不可用。或者您没有使用 -g 选项编译 exefile。当您是 gdb 的新手时会发生什么,您可能已经给出了命令文件 argfile 而不是 运行 argfile。请检查。
我遇到了同样的错误。我通过使用 Gparted 软件增加交换 space 解决了我的问题。 1- 首先使用 "sudo apt-get install gparted" 安装 Gparted 2- 打开 Gparted 并右键单击交换然后 select Resize/Move (注意:只有在交换内存之前或之后有未分配的内存时,您才能增加交换大小)