C分段故障(核心转储)链接列表

时间:2015-09-30 20:58:40

标签: c memory segmentation-fault void-pointers coredump

我一直遇到Segmentation Fault (core dumped)运行时错误,我无法弄清楚原因。

我的代码:

struct Node
{
    void *next;
    void *val;
};
typedef struct Node* NodePtr;

struct List
{
    NodePtr head;
};
typedef struct List* ListPtr;

ListPtr create()
{
    ListPtr ptr = malloc(sizeof(struct List));

    return ptr;
}

int insert(ListPtr list, void *obj)
{
    NodePtr newObj = malloc(sizeof(struct Node));

    //Cast next as a self referencing Node
    newObj->next = (NodePtr) newObj->next;

    //Point to beginning of list
    NodePtr current = list->head;

    if(list->head == NULL)
    {
        newObj->val = obj;
        list->head->next = newObj;
        newObj->next = NULL;

        return 1;
    }

    return 0;
}

int main(int argc, char *argv[])
{
    int x = 2;
    int *p = &x;

    ListPtr thing = create();

    insert(thing, p);

    return 0;
}

错误在于:list->head->next = newObj经过一些调试。我以为我必须为list-> head->接下来分配内存,但是当我添加代码时,它仍然给了我同样的错误。我错了或者没有正确分配内存吗?任何帮助将不胜感激,谢谢!

4 个答案:

答案 0 :(得分:1)

检查list->head是否为NULL,然后对其执行某些操作。将其更改为if(list->head != NULL) { ... }

答案 1 :(得分:1)

一想到,malloc不保证分配的内存为空。在分配后将所有值设置在重要位置是一种很好的做法。 list-> head可能不为null

另外:newObj-> next =(NodePtr)newObj-> next; 没有设置为合理值,它设置为设置的内存 - 你打算newObj-> next =(NodePtr)newObj; ?

如果为null,则不应引用

list-> head。 list-> head-> next只有在它不为空时才有效。

如果你真的想要建立一个列表,

newObj->val = obj;
if (list->head == NULL) { newObj->next = list->head; }
list->head = newObj;

或者向下移动列表 - > head-> next chain直到next为null,并将其设置为newObj-> next。如果这样,那么它可能是一个好主意,newObj-> next应该设置为NULL而不是它本身。

可能想知道你的列表将如何表现 - 它是圆形的吗?它是从头部(list-> head)还是尾部(last - > next)生长的?当listObject-> next == NULL或listObject-> next == listObject?

时,您是否发现了尾部?

答案 2 :(得分:1)

把它放在一起,运行正常。

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


struct Node {
        void *next;
        void *val;
};
typedef struct Node* NodePtr;

struct List {
    NodePtr head;
};
typedef struct List* ListPtr;

ListPtr CreateList() {
    ListPtr ptr = malloc(sizeof(struct List));
    return ptr;
}

void Insert(ListPtr list, void *obj) {
        // create and initialize new node
    NodePtr newObj = malloc(sizeof(struct Node));
    newObj->val = obj;
    newObj->next = NULL;

    //Point to beginning of list
    NodePtr curr = list->head;
    // Add node to the list
    if(curr == NULL) // if no head node, make newObj the head node
    {
        list->head = newObj;
    }
    else{ // otherwise traverse the list until you find the last node (the one that points to a null as the next)
        while(1) {
                if(curr->next != NULL) {
                        curr = curr -> next;
                } else {
                        curr->next = newObj;
                }
                list->head = newObj;
                newObj->val = obj;
                list->head->next = newObj;
                newObj->next = NULL;
        }
    }
}
int main() {
    int x = 2;
    int *p = &x;

    ListPtr thing = CreateList();

    Insert(thing, p);

    return 0;
}

答案 3 :(得分:1)

我意识到这个答案主要是风格。但我认为(坏)风格和(坏)习惯是(坏)编程的一个(重要的)部分。总结一下......

  • (在大多数情况下)不需要typedef;他们只是为已经存在的东西引入别名。
  • [七条规则]人类读者拥有可以跟踪的有限数量的标识符(&#34;名称&#34;)。这可能是7.最小化不同单词的数量使阅读更容易。
  • 另外,读者必须记住xPtr和xNode是相关的(typeof * xPtr === typeof xNode)
  • 在阅读源代码时,关键字和特殊字符标记(例如运算符)不会将计数作为标识符,因为您不必记住它们。 (语法 - highligting也有帮助)
  • 如果只有一种表达方式的方式,则不会出现iPtr *p; p = (qPtr) malloc (sizeof xNode);
  • 等错误
  • 创建另一个结构(为它的+ typedef),只是为了容纳一个 root 指针,将会破坏你的心灵命名空间。

现在重做(预期)代码:

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

struct node {
    struct node *next;
    void *payload;
    };

struct node *root=NULL;

void initialize() { /* nothing .... */ }

int insert(struct node **pp, void *pv) {
   struct node *p;

   p = malloc(sizeof *p);
   if (!p) { /* handle error */ return -1; }

   p->payload = pv;
   p->next = *pp;
   *pp = p;
   return 1; /* inserted one element */
 }

int main(void)
{
int i;

i=666;

 /* note: this function call will pass a pointer to a local variable `i`
 ** to the insert() function, which will remember it.
 ** This is generally a bad idea, to say the least.
 */
insert( &root, &i);

return 0;
}