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 <[email protected]>
0x08048462 <+21>: lea 0x1c(%esp),%eax
0x08048466 <+25>: mov %eax,0x4(%esp)
0x0804846a <+29>: movl $0x8048555,(%esp)
0x08048471 <+36>: call 0x8048320 <[email protected]>
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 <[email protected]>
0x0804848d <+64>: jmp 0x804849b <main+78>
=> 0x0804848f <+66>: movl $0x8048569,(%esp)
0x08048496 <+73>: call 0x8048310 <[email protected]>
0x0804849b <+78>: mov $0x0,%eax
0x080484a0 <+83>: leave
0x080484a1 <+84>: ret
то, что я просматриваю, - $0x208c. Когда я набираю x/xw 0x208c, он возвращает мне ошибку, в которой говорится, что невозможно получить доступ к памяти по адресу 0x208c. Когда я печатаю Info регистры и смотрю на eax, он говорит значение, которое я предоставил. Таким образом, в основном эта программа сравнивает два значения и в зависимости от того, что печатает что-то. Проблема в том, что это домашнее задание из университета, и у меня нет кода. Надеюсь, ты поможешь. Спасибо.
Ответы
Ответ 1
Когда я набираю 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
как указатель, этот указатель не указывает на читаемую память.
я наконец решил использовать инструкцию печати вместо x/xw
Кажется, вы не понимаете разницы между командами print
и examine
. Рассмотрим этот пример:
int foo = 42;
int *pfoo = &foo;
Свыше, print pfoo
предоставит вам адрес foo
, а x pfoo
предоставит вам значение, сохраненное по этому адресу (т.е. значение foo
).
Ответ 2
Я узнал, что невозможно исследовать mmap
ed память, у которой нет флага 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);
и вуаля, память может быть рассмотрена.
Ответ 3
Неинициализированные указатели
Это ретроспективно, но это то, что заставляло 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
Но в сложной программе, конечно, и где адрес был чем-то случайным, отличным от нуля.
Ответ 4
В моем случае проблема была вызвана вызовом 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, был несколько случайным. И это только иногда давало сбои и заканчивалось очень длительным процессом.
Ответ 5
Если GDB сообщает, что адрес памяти не найден, это означает, что символ недоступен в исполняемом файле, открытом GDB, или в файле exefilename. ИЛИ вы не скомпилировали exefile с опцией -g. Что происходит, когда вы новичок в gdb, вы могли дать командный файл argfile вместо запуска argfile. Пожалуйста, проверьте.