“无法访问地址 0x208c 处的内存”错误

问题描述 投票:0回答:6

反汇编代码:

   0x0804844d <+0>:     push   %ebp
   0x0804844e <+1>:     mov    %esp,%ebp
   0x08048450 <+3>:     and    $0xfffffff0,%esp
   0x08048453 <+6>:     sub    $0x20,%esp
   0x08048456 <+9>:     movl   $0x8048540,(%esp)
   0x0804845d <+16>:    call   0x8048310 <puts@plt>
   0x08048462 <+21>:    lea    0x1c(%esp),%eax
   0x08048466 <+25>:    mov    %eax,0x4(%esp)
   0x0804846a <+29>:    movl   $0x8048555,(%esp)
   0x08048471 <+36>:    call   0x8048320 <scanf@plt>
   0x08048476 <+41>:    mov    0x1c(%esp),%eax
   0x0804847a <+45>:    cmp    $0x208c,%eax
   0x0804847f <+50>:    jne    0x804848f <main+66>
   0x08048481 <+52>:    movl   $0x8048558,(%esp)
   0x08048488 <+59>:    call   0x8048310 <puts@plt>
   0x0804848d <+64>:    jmp    0x804849b <main+78>
=> 0x0804848f <+66>:    movl   $0x8048569,(%esp)
   0x08048496 <+73>:    call   0x8048310 <puts@plt>
   0x0804849b <+78>:    mov    $0x0,%eax
   0x080484a0 <+83>:    leave  
   0x080484a1 <+84>:    ret

我要检查的是

$0x208c
。当我输入
x/xw 0x208c
时,它返回一个错误:

无法访问地址 0x208c 处的内存。

当我输入 Info registers 并查看

eax
时,它会显示我提供的值。

基本上,这个程序会比较两个值,并根据结果打印出一些内容。

c gdb
6个回答
28
投票

当我输入

x/xw 0x208c
时,它给我返回错误,显示
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
解释为指针,则该指针不会指向可读内存。

我终于想出了使用 print 语句代替 x/xw

您似乎不理解

print
examine
命令之间的区别。考虑这个例子:

int foo = 42;
int *pfoo = &foo;

通过上述,

print pfoo
将为您提供foo
地址
x pfoo
将为您提供存储在该地址的(即
foo
的值)。


7
投票

我发现不可能检查没有

mmap
标志的
PROT_READ
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);

瞧,可以检查记忆了。


1
投票

未初始化的指针

回想起来,这很明显,但这就是导致 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

但是当然是在一个复杂的程序中,并且地址是不同于零的随机值。


1
投票

在我的例子中,问题是由于调用长度大于 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 的大小有些随机。它只是有时会崩溃,并且是一个非常漫长的过程的结束。


1
投票

如果GDB说找不到内存地址,则意味着该符号在gdb或通过文件exefilename打开的可执行文件中不可用。或者您尚未使用 -g 选项编译 exe 文件。当您是 gdb 新手时,您可能给出了命令 file argfile 而不是 run argfile,会发生什么情况。请检查。


-3
投票

我遇到了同样的错误。我通过使用 Gparted 软件增加交换空间解决了我的问题。 1-首先使用“sudo apt-get install gparted”安装Gparted 2- 打开 Gparted 并右键单击交换,然后选择调整大小/移动 (注意:只有在交换内存之前或之后有未分配的内存时,您才能增加交换大小)

© www.soinside.com 2019 - 2024. All rights reserved.