简体   繁体   English

通过链接列表获取段错误

[英]Getting a segfault with linked list

Apologies for the very basic question, but I can't figure this out. 对于最基本的问题表示歉意,但我无法弄清楚。 I am trying to build a simple linked list and append some values to it in C. 我正在尝试建立一个简单的链表,并在C中附加一些值。

Below is the list.c file 以下是list.c文件

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

#include "./list.h"

int main(int argc, char *argv[]) {
    int arr[] = {1,2,3,4};
    List *list = createList();
    int i = 0;
    for(i = 0; i < 4; i++) {
        appendList(list, arr[i]);
    }
    return 0;
}

List *createList() {
    List *list = malloc(sizeof(List));
    if(list == NULL) {
        return NULL;
    }

    list->head = malloc(sizeof(Node));
    list->tail = malloc(sizeof(Node));
    if(list->head == NULL || list->tail == NULL) {
        free(list);
        return NULL;
    }

    list->size = 0;
    return list;
}

void appendList(List *list, int num) {
    if(list->head->value == 0) {
        list->head->value = num;
        list->tail->value = num;
        return;
    }
    Node *current = calloc(1, sizeof(Node));
    current = list->head;
    while(current->next != NULL) {
        current = current->next;
    }
    current->next = calloc(1, sizeof(Node));
    if(current->next == NULL) {
        free(current->next);
        printf("Failed to allocate memory");
        exit(1);
    }
    current->next->value = num;
    list->size += 1;
    list->tail = current->next;
}

And below is the header file 下面是头文件

#ifndef List_h
#define List_h

#include <stdlib.h>

typedef struct node {
    int value;
    struct node *next;
} Node;

typedef struct {
    Node *head;
    Node *tail;
    int size;
} List;

List *createList();
void appendList(List *, int num);
Node *removeList(List *);
void printList(List *);

#endif

While running through a debugger, my code seems to be working fine, which makes even less sense. 通过调试器运行时,我的代码似乎运行正常,这变得毫无意义。

I assume my issue is in the while loop inside of appendList , where I am trying to access some unallocated piece of memory. 我认为我的问题是在appendListwhile循环中,我试图在其中访问一些未分配的内存。 Is the issue then with the check I am making, current->next != NULL ? 我正在做的检查是否是问题, current->next != NULL Does accessing an unallocated piece of memory necessary return NULL ? 访问未分配的内存是否必须返回NULL

Hmm, well my thoughts are that you've created the initial head and tail Node s and you didn't set its value. 嗯,我的想法是您已经创建了初始的头Node和尾Node ,但是您没有设置它的值。 Later you use value to determine whether or not you need to add another node or set head and tail to the value passed: 以后,您可以使用value来确定是否需要添加另一个节点或将头尾设置为传递的值:

void appendList(List *list, int num) {
    if(list->head->value == 0) {
        list->head->value = num;
        list->tail->value = num;
        return;
    }
    ...

The memory returned from malloc will not be necessarily zero, so your algorithm should ensure that all values are set before proceeding. 从返回的内存malloc不一定是零,那么你的算法应确保所有值都在继续之前设置。

You then proceed to reach the end of your list: 然后,您进入列表的末尾:

Node *current = calloc(1, sizeof(Node));
current = list->head;
while(current->next != NULL) {
    current = current->next;
}

However, again, while list->head exists, you never set the value of list->head->next ! 但是,同样,当list->head存在时,您永远不会设置list->head->next的值! Following an unassigned pointer is not going to end nicely for you in the best of cases. 在最佳情况下,跟随未分配的指针并不能很好地结束。

Consider creating a method to create a new node: 考虑创建一种方法来创建新节点:

Node* createNode() {
    Node* node = malloc(sizeof(Node));
    if(node == NULL) {
        return NULL;
    }
    node->value = 0;
    node->next = NULL;
    return node;
}

Also please note that there's a minor correction to the code here (unrelated to your segmentation fault, but could still create memory leak): 还请注意,此处的代码有一些小的更正(与分段错误无关,但仍可能导致内存泄漏):

list->head = malloc(sizeof(Node));
list->tail = malloc(sizeof(Node));
if(list->head == NULL || list->tail == NULL) {
    free(list);
    return NULL;
}

Note that it is possible for list->head to correctly be assigned memory and list->tail to not be correctly assigned memory. 注意,可能的 list->head正确地是分配存储器和list->tail 被正确分配存储器。 In that case, you risk having a memory leak for list->head . 在这种情况下,您可能会发生list->head的内存泄漏。 Please take the necessary precautions. 请采取必要的预防措施。

Especially in embedded systems, the code compiled for debug mode and the one for release mode can differ. 特别是在嵌入式系统中,为调试模式编译的代码与为发布模式编译的代码可能会有所不同。 So, for me, there is no surprise that your code works in debug and won't in release. 因此,对我来说,您的代码可以在调试中工作并且不会在版本中发布就不足为奇了。

When creating linked lists using malloc, it is possible that the compiler sets the address of your "struct node * next" element, a non-accessible location in memory. 使用malloc创建链接列表时,编译器可能会设置“结构节点*下一步”元素的地址,这是内存中不可访问的位置。 So if you try to access it, you'll get a segfault. 因此,如果尝试访问它,则会出现段错误。 (or BAD_EXC in MacOS) (或MacOS中的BAD_EXC)

If you suspect that malloc is your problem, try creating a small list with no malloc and see if you have segfault, ie use: 如果您怀疑问题是malloc,请尝试创建一个没有malloc的小列表,看看是否存在segfault,即使用:

struct node myNode;
struct node* pmyNode = &myNode;

In your while loop, I suppose, you are trying to go to the last element of your list. 我想在您的while循环中,您正在尝试转到列表的最后一个元素。 So, instead of: 因此,代替:

while(current->next != NULL) {
    current = current->next;
}

Try to do this: 尝试这样做:

last_linked_list_element->next = last_linked_list_element;

current = first_linked_list_element;

while(current != current->next) {
    current = current->next;
}

You will break out of the loop when you are at the last element of your list. 当您位于列表的最后一个元素时,您将跳出循环。

Another solution would be to try: 另一个解决方案是尝试:

last_linked_list_element->next = NULL;

or 要么

last_linked_list_element->next = &random_identifier;

This will make sure that the pointer locates to an accesible location in memory. 这将确保指针定位到内存中的可访问位置。 Does this solve your problem? 这样可以解决您的问题吗?

In addition to the previous post, in the following code: 除了上一篇文章之外,下面的代码:

Node *current = calloc(1, sizeof(Node));
current = list->head;
while(current->next != NULL) {
    current = current->next;
}

you should to delete the line Node *current = calloc(1, sizeof(Node)); 您应该删除行Node *current = calloc(1, sizeof(Node)); because in this way you allocate memory and than don't use it (subsequently you assign currect pointer to another value). 因为以这种方式分配内存而不使用内存(随后将currect指针分配给另一个值)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM