Если вы на Mac работает некоторую версию OS X, вы должны иметь установлены gcc и gdb. Если нет, их легко загрузить и установить. Я работаю в системе Linux, но шаги и результаты ниже должны быть похожими на OS X.
Для того чтобы увидеть исходный код в отладчике, вам необходимо скомпилировать его с опцией -g
: gcc -o myprog -g myprog.c
, В противном случае вы увидите только сгенерированный машинный код.
На этом этапе вы можете либо запустить программу в обычном режиме, либо оставить файл ядра, который вы загрузите в gdb, или запустите программу в gdb и пройдите через нее по строкам.
Я взял на себя смелость принимать кода и создания полной программы из него:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int **values;
int i, j;
values = malloc(10 * sizeof(int *));
for (i = 0; i < 10; i++){
for (j = 0; j < 10; j++){
values[i][j] = i * j;
}
}
for (i = 0; i < 10; i++)
printf("%d ", values[i][i]);
printf("\n");
return 0;
}
Мы будем строить это с отладкой:
$ gcc -o example -g -std=c99 -pedantic -Wall -Werror example.c
и запустить его в GDB:
$ gdb example
GNU gdb (GDB) SUSE (7.1-8.9.1)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-suse-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/fbgo448/prototypes/coredump/example...done.
(gdb)
Первое, что мы сделаем это установить точку останова в main
; это заставит программу, чтобы сделать паузу, как только он войдет в основную функцию:
(gdb) break main
Breakpoint 1 at 0x4005a0: file example.c, line 9.
Теперь мы начнем программу, работающую в среде GdB; он будет работать до следующей точки останова:
(gdb) r
Starting program: /home/fbgo448/prototypes/coredump/example
Breakpoint 1, main() at example.c:9
9 values = malloc(10 * sizeof(int *));
Вы можете выполнить одну строку в то время, как так:
(gdb) n
10 for (i = 0; i < 10; i++){
Вы можете проверить содержимое переменных или произвольных ячеек памяти:
(gdb) p values
$1 = (int **) 0x501010
(gdb) p *values
$2 = (int *) 0x0
(gdb) x/1x 0x501010
0x501010: 0x00000000
(gdb) x/1b 0x501010
0x501010: 0x00
(gdb) x/10b 0x501010
0x501010: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x501018: 0x00 0x00
(gdb) x/10x 0x501010
0x501010: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x501018: 0x00 0x00
Надеюсь, вы видите проблему уже, но если нет, мы можем «продолжить» программу и пропустить ее до тех пор, пока она не сработает:
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x00000000004005e3 in main() at example.c:12
12 values[i][j] = i * j;
Вы получаете segfault, пытающийся присвоить values[i][j]
. Давайте посмотрим еще раз:
(gdb) p i
$3 = 0
(gdb) p j
$4 = 0
(gdb) p values
$5 = (int **) 0x501010
(gdb) p values[i]
$6 = (int *) 0x0
(gdb) p values[i][j]
Cannot access memory at address 0x0
Другие люди указали проблему; вы выделили достаточно места для 10 указателей на int
, но вы не выделили ничего для этих указателей, чтобы указать на. Вы пропустили шаг в вашем процессе выделения:
values = malloc(10 * sizeof *values); // sizeof *values == sizeof (int *)
if (values)
{
for (i = 0; i < 10; i++)
{
values[i] = malloc(10 * sizeof *values[i]); // sizeof *values[i] == sizeof (int)
if (values[i])
{
for (j = 0; j < 10; j++)
{
values[i][j] = i * j;
}
}
}
}
GDB это достаточно мощный отладчик, если несколько боли использовать.
Используйте отладчик, такой как GDB. –
Попробуйте значения 'int [10] [10];' и no malloc; или 'int (* values) [10];' и values = malloc (10 * 10 * sizeof (int)); '. Также поместите 'fflush (stdout);' после каждой отладки 'printf'. – Marian
У вас есть malloc'd для 10 указателей, но вы никогда не заставляете их указывать на что-либо. – Roddy