2014-11-09 5 views
0

У меня есть ошибка Segmentation fault (core dumped).Malloc не может выделить память для архитектуры

main.c

#include "header1.h" 

#include <stdlib.h> 
#include <stdio.h> 

int main(int argc, char** argv) { 
     struct t_list *list = NULL; 
     doFill(list); 
     printf("%s\n", list->name); 
     free(list); 
     return 0; 
} 

header1.h

#ifndef HEADER1_H 
#define HEADER1_H 

struct t_list { 
    char *name; 
    struct t_list *next; 
}; 

void doFill(struct t_list *list); 

#endif 

worker.c

#include "header1.h" 
#include <stdlib.h> 

void doFill(struct t_list *list) { 
    list = (struct t_list *) malloc(sizeof(struct t_list)); 
    char *tmp = "somename"; 
    list->name = tmp; 
    list->next = NULL; 
} 

Когда я запускаю это (gcc -g main.c worker.c -o test) я получаю (на линии с printf в main.c):

Segmentation fault (core dumped) 

В gdb я вижу:

Temporary breakpoint 1, main (argc=1, argv=0x7fffffffddf8) at main.c:8 
8  struct t_list *list = NULL; 
(gdb) next 
9  doFill(list); 
(gdb) step 
doFill (list=0x0) at worker.c:6 
6  list = (struct t_list *) malloc(sizeof(struct t_list)); 
(gdb) p list 
$1 = (struct t_list *) 0x0 
(gdb) next 
7  char *tmp = "somename"; 
(gdb) p list 
$2 = (struct t_list *) 0x0 

Как вы можете видеть malloc в worker.c не выделяет память для переменная list (указатель до и после malloc указывает на 0x0).

Если переместить код из doFill процедуры в main.c она работает правильно:

main.c

#include "header1.h" 

#include <stdlib.h> 
#include <stdio.h> 

int main(int argc, char** argv) { 
    struct t_list *list; 
    list = (struct t_list *) malloc(sizeof(struct t_list)); 
    char *tmp = "somename"; 
    list->name = tmp; 
    list->next = NULL; 
    printf("%s\n", list->name); 
    free(list); 
    return 0; 
} 

$ gcc -g main.c -o test 
$ ./test 
somename 

Как это возможно? Что я делаю неправильно?

gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) 
+3

'недействительным doFill (STRUCT t_list * list) 'Вам нужно' ** 'здесь, чтобы сделать выделение видимым вызывающим. –

+0

[Не произносить результат malloc (и друзей)] (http://stackoverflow.com/q/605845). – Deduplicator

+0

@Deduplicator Спасибо за ссылку, я прочитал книгу «Язык программирования C», написанную создателями языка c.Они выдали результаты malloc, я тоже бросаю. Но книга была написана в 1988 году, и я согласен с тем, что это могло быть устаревшим поведением. – zaratustra

ответ

1

Параметры в C передаются копией. Изменения, внесенные вами в list внутри doFill(), не распространяются на main(), что означает, что list всегда NULL в main(). Попробуйте передавая указатель на указатель вместо:

#include "header1.h" 

#include <stdlib.h> 
#include <stdio.h> 

int main(int argc, char** argv) { 
     struct t_list *list = NULL; 
     doFill(&list); 
     printf("%s\n", list->name); 
     free(list); 
     return 0; 
} 

А затем изменить doFill() соответственно:

#include "header1.h" 
#include <stdlib.h> 

void doFill(struct t_list **list) { 
    *list = malloc(sizeof(**list)); 
    char *tmp = "somename"; 
    (*list)->name = tmp; 
    (*list)->next = NULL; 
} 
+1

Спасибо, мужчина, он работает. – zaratustra

2

Вы не получаете обратно новое значение list. Фактически, прохождение list в абсолютно бесполезно. Лучше пройти в name для этого узла.

typedef struct t_list List; 

List *newListNode(char *name) { 
    List *list = malloc(sizeof(*list)); 
    if (!list) return NULL; 
    list->name = strdup(name); 
    if (!list->name) { free(list); return NULL; } 
    list->next = NULL; 
    return list; 
} 

char *strdup(char *src) { // if strdup doesn't already exist. 
    char *dst = malloc(strlen(src) + 1); 
    if (!dst) return NULL; 
    strcpy(dst, src); 
    return dst; 
} 

Чтобы добавить узлы в передней части списка:

List *listAdd(List *list, char *name) { 
    List *newnode = newListNode(name); 
    if (!newnode) return NULL; 
    if (list) newnode->next = list; 
    return newnode; 
} 

Чтобы удалить список, не забудьте удалить malloc ред строки:

void deleteList(List *list) { 
    for (List *next; list; list = next) { 
    next = list->next; 
    free(list->name); 
    free(list); 
    } 
}