2014-01-29 2 views
1

То, что я пытаюсь сделать, это создать массив 10x10 и распечатать только значения по диагонали, в настоящее время это происходит, поэтому у меня есть пара вопросов. 1. Что является самым простым способом отладки segfault на Mac с помощью оболочки терминала? 2. Я пытаюсь выяснить, где в этой функции это segfaults? Я попытался добавить простой оператор printf выше строки values ​​= malloc ..., и он даже не сделал это так далеко, я не думаю.Отладка ошибки сегментации в программе C

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"); 
+1

Используйте отладчик, такой как GDB. –

+0

Попробуйте значения 'int [10] [10];' и no malloc; или 'int (* values) [10];' и values ​​= malloc (10 * 10 * sizeof (int)); '. Также поместите 'fflush (stdout);' после каждой отладки 'printf'. – Marian

+0

У вас есть malloc'd для 10 указателей, но вы никогда не заставляете их указывать на что-либо. – Roddy

ответ

1

Вам необходимо выделить как «столбцы», так и «строки». Прямо сейчас вы выделяете указатели на целые числа, вам также нужно выделить сами целые числа.

int **values; 

int i, j; 
values = (int**)malloc(10 * sizeof(int *)); 

for(i = 0; i < 10; i++){ 
    values[i] = (int*)malloc(10 * sizeof(int)); //Small edit. 
} 

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"); 

Я не знаю много о Mac, но я уверен, что вы можете использовать GDB. Скомпилируйте свою программу с помощью параметров отладки, чтобы создать исполняемый файл с информацией об отладке, а при сбое программы он сгенерирует дамп ядра. Откройте этот дамп ядра с помощью gdb и bon appetit.

0

Ошибка сегментации возникает, когда ваш указатель имеет адрес, который указывает на недопустимый сегмент памяти. Эта ситуация возникает, когда она не инициализируется. Большую часть времени стоимость мусора вызывает такой отказ.

Чтобы избежать этого, используйте calloc вместо malloc(), потому что calloc() выделяет память, а также инициализирует нуль.

Также вы должны выделить пространство для 2-го измерения.

int **values; 

int i, j; 
values = (int**)calloc(10 * sizeof(int *)); 

for(i = 0; i < 10; i++){ 
    values[i] = (int*)calloc(10 * sizeof(int)); //Small edit. 
} 

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"); 
0

Изменение кода будет самым простым способом. Вот как:

int i, j; 
values = malloc(10 * sizeof(int*)); 
for (i = 0; i < 10; i++) 
{ 
    values[i] = malloc(10 * sizeof(int)); 
    for (j = 0; j < 10; j++) 
    { 
     values[i][j] = i * j; 
    } 
} 

И не забудьте free все это, когда вы сделали:

int i; 
for (i = 0; i < 10; i++) 
{ 
    free(values[i]); 
} 
free(values); 
+0

бесплатно, все, что нам нужно сделать, это бесплатно (10 * sizeof (int *)) .. вы просто бесплатно, точно, что вы malloc'd правильно? – user1837411

+0

@ user1837411 В этом случае для освобождения требуется 11-invocations 'free()'; такое же количество 'free()' s как 'malloc()' s. – WhozCraig

+0

Отвечено обновлено; не забудьте проголосовать за него, если это поможет вам ... –

1

Если вы на 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 это достаточно мощный отладчик, если несколько боли использовать.

Смежные вопросы