Malloc不能为结构分配内存。

时间:2022-08-25 09:10:23

I have the Segmentation fault (core dumped) error.

我有分段错误(core dump)错误。

main.c

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

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

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;
}

When I run this (gcc -g main.c worker.c -o test) I get (on the line with printf in main.c):

当我运行这个(gcc -g main)时。c工人。c -o测试)我得到(在main.c中与printf一致):

Segmentation fault (core dumped)

In gdb I see:

在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

As you can see malloc in worker.c doesn't allocate memory for the list variable (the pointer before and after malloc points at 0x0).

正如你在工作中看到的malloc。c不为列表变量分配内存(在0x0中malloc点之前和之后的指针)。

If I move the code from the doFill procedure in main.c it works correctly:

如果我把代码从主要的doFill过程中移动。c它工作正常:

main.c

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

How is it possible? What do I do wrong?

怎么可能?我做错了什么?

gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)

2 个解决方案

#1


1  

Parameters in C are passed by copy. The changes you make to list inside of doFill() are not propagated back to main(), which means that list is always NULL in main(). Try passing a pointer to pointer instead:

C中的参数通过copy传递。在doFill()中列出的更改不会传播回main(),这意味着列表在main()中总是为NULL。试着将一个指针传递给指针:

#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;
}

And then change doFill() accordingly:

然后相应地改变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;
}

#2


2  

You aren't receiving back the new value of list. In fact, passing list in is totally useless. Better to pass in the name for this node.

您没有收到新的列表值。事实上,通过列表是完全没用的。最好将这个节点的名称传递给它。

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;
}

To add nodes to the front of the list:

将节点添加到列表的前面:

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

To delete the list, remember to delete the malloced strings:

要删除列表,请记住删除malloced字符串:

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

#1


1  

Parameters in C are passed by copy. The changes you make to list inside of doFill() are not propagated back to main(), which means that list is always NULL in main(). Try passing a pointer to pointer instead:

C中的参数通过copy传递。在doFill()中列出的更改不会传播回main(),这意味着列表在main()中总是为NULL。试着将一个指针传递给指针:

#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;
}

And then change doFill() accordingly:

然后相应地改变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;
}

#2


2  

You aren't receiving back the new value of list. In fact, passing list in is totally useless. Better to pass in the name for this node.

您没有收到新的列表值。事实上,通过列表是完全没用的。最好将这个节点的名称传递给它。

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;
}

To add nodes to the front of the list:

将节点添加到列表的前面:

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

To delete the list, remember to delete the malloced strings:

要删除列表,请记住删除malloced字符串:

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