C - 链表中的分段 - 错误

时间:2016-04-06 20:11:16

标签: c linked-list segmentation-fault malloc

我理解当您尝试访问程序范围之外的内存时会发生设置错误,但我无法弄清楚我的发生位置或原因。我有一个列表定义:      * ListType list = NULL; , 然后我将数据添加到List中,调用main中的add函数:       addNodeToList(& list,song);

void addNodeToList(ListType **list, SongType *song)
{
    printf("Starting Add");

    NodeType *newNode = malloc(sizeof(NodeType));
    NodeType *currNode;
    currNode = (*list)->head;
    newNode->data = song;
    newNode->next = NULL;

    if(currNode == NULL) {
        printf("List is Empty");
        (*list)->tail = newNode;
        (*list)->head = newNode;
    }
    else {
        (*list)->tail->next = newNode;
        (*list)->tail = newNode;
    }

}

我传递的歌曲已正确初始化,我可以访问它的元素,所以我知道这不会导致seg错误。任何帮助将非常感谢!

typedef struct Song {
  char title[MAX_STR];
  char artist[MAX_STR];
  char album[MAX_STR];
  char duration[MAX_STR];
} SongType;

typedef struct Node {
  struct Node *next;
  SongType *data;
} NodeType;

typedef struct List {
  NodeType *head;
  NodeType *tail;
} ListType;

3 个答案:

答案 0 :(得分:3)

如果您要声明

,请在main

 ListType* list = NULL;

然后在你的功能中你打电话

 (*list)->head

解除引用(*list)没问题,但是只要你->head它尝试取消引用原始NULL作业就行了。您需要先为list分配一些空间。

答案 1 :(得分:1)

您的主叫代码似乎包含:

ListType *list = NULL;

你打电话给你的函数:

addNodeToList(&list, song);

并在您的addNodeToList()函数中:

NodeType *currNode;
currNode = (*list)->head;

这意味着您将取消引用空指针(*list),这会导致代码崩溃。至少,在设置*list == NULL之前检查是否currNode,但是您需要重新考虑代码以处理list是空指针的情况。

此代码编译并运行。它通过在必要时分配列表来避免这个问题:

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

enum { MAX_STR = 64 };

typedef struct Song
{
    char title[MAX_STR];
    char artist[MAX_STR];
    char album[MAX_STR];
    char duration[MAX_STR];
} SongType;

typedef struct Node
{
    struct Node *next;
    SongType *data;
} NodeType;

typedef struct List
{
    NodeType *head;
    NodeType *tail;
} ListType;

void addNodeToList(ListType **list, SongType *song);

void addNodeToList(ListType **list, SongType *song)
{
    printf("Starting Add\n");
    assert(list != NULL);

    if (*list == NULL)
    {
        *list = malloc(sizeof(**list));
        assert(*list != 0);  // Too lazy for production
        (*list)->head = 0;
        (*list)->tail = 0;
        printf("List created\n");
    }
    NodeType *newNode = malloc(sizeof(NodeType));
    newNode->data = song;
    newNode->next = NULL;
    printf("Node created\n");

    NodeType *currNode = (*list)->head;
    if (currNode == NULL)
    {
        printf("List is Empty\n");
        (*list)->tail = newNode;
        (*list)->head = newNode;
    }
    else
    {
        (*list)->tail->next = newNode;
        (*list)->tail = newNode;
    }
    printf("Node added - all done\n");
}


int main(void)
{
    ListType *list = NULL;
    SongType  data = { "Title", "Artist", "Album", "2m 30s" };
    SongType *song = &data;

    printf("Add song once\n");
    addNodeToList(&list, song);
    printf("Add song again\n");
    addNodeToList(&list, song);
    return 0;
}

示例运行:

Add song once
Starting Add
List created
Node created
List is Empty
Node added - all done
Add song again
Starting Add
Node created
Node added - all done

代码漏像筛子;没有记忆被释放。

答案 2 :(得分:0)

问题涉及此声明

ListType *list = NULL;

您可能无法致电addNodeToList以获取以此方式初始化的列表。否则会出现未定义的行为。

您应该按以下方式声明列表

ListType list = { NULL, NULL };

此外,函数addNodeToList可以声明为更简单

void addNodeToList(ListType *list, SongType *song);
                   ^^^^^^^^^^^^^^ 

您可以将其称为

addNodeToList( &list, song );

例如

void addNodeToList( ListType *list, SongType *song )
{
    printf("Starting Add");

    NodeType *newNode = malloc( sizeof( NodeType ) );

    if ( newNode != NULL )
    {
        newNode->data = song;
        newNode->next = NULL;

        if ( list->tail == NULL )
        {
            printf( "List is Empty\n" );
            list->head = list->tail = newNode;
        }
        else
        {
            list->tail->next = newNode;
            list->tail = newNode;
        }
    }
}

或者如果你想要一个指向列表的指针,那么你应该写

ListType *list = malloc( sizeof( ListType ) );
list->head = list-tail = NULL;;

然后调用函数定义我用以下方式显示

addNodeToList( list, song );