Malloc无法为结构分配内存

时间:2014-11-09 14:14:49

标签: c gcc struct segmentation-fault malloc

我有Segmentation fault (core dumped)错误。

的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)时,我得到(在main.c中与printf一致):

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

正如您在worker.c中看到的那样malloc没有为list变量分配内存(malloc点之前和之后的指针0x0

如果我从main.c中的doFill过程移动代码,它可以正常工作:

的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)

2 个答案:

答案 0 :(得分: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 ed字符串:

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

答案 1 :(得分: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;
}