GDB не может получить доступ к ошибке адреса памяти

Вот мой код disas:

   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, он говорит о значении, которое я предоставил. Так что в основном эта программа сравнивает два значения и в зависимости от того, что печатает что-то. Проблема в том, что это домашняя работа из университета, а у меня нет кода. Надеюсь, вы можете помочь. Спасибо.

3 ответа

Решение

Когда я печатаю 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).

Я обнаружил, что это невозможно исследовать mmapпамять, которой нет PROT_READ флаг. Это не проблема OPs, но она была моей, и сообщение об ошибке то же самое.

Вместо

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 сообщает, что адрес памяти не найден, это означает, что символ недоступен в исполняемом файле, открытом GDB, или в файле exefilename. ИЛИ вы не скомпилировали exefile с опцией -g. Что происходит, когда вы новичок в gdb, вы могли дать командный файл argfile вместо запуска argfile. Пожалуйста, проверьте.

Неинициализированные указатели

Это довольно очевидно в ретроспективе, но именно это заставило 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

Но в сложной программе, конечно, и адрес был чем-то случайным, отличным от нуля.

В моем случае проблема была вызвана вызовом munmap с длиной больше, чем mmap:

#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);
    }   

}

Таким образом, unmap отображает также отображения для стеков нескольких потоков. Довольно неприятный, потому что он сделал дамп ядра невозможным для моего текущего уровня квалификации. Тем более что в исходной задаче размер, передаваемый в munmap, был несколько случайным. И это только иногда давало сбои и заканчивалось очень длительным процессом.

У меня такая же ошибка. Я решил свой случай с увеличением пространства подкачки с помощью программного обеспечения Gparted. 1- Сначала установите Gparted с помощью "sudo apt-get install gparted" 2- Откройте Gparted и щелкните правой кнопкой мыши на подкачке, затем выберите Изменить размер / Переместить (Примечание: вы можете увеличить размер подкачки, только если у вас есть нераспределенная память до или после подкачки памяти)

Другие вопросы по тегам