2013-01-08 132 views
0

我不问关于效率,进一步列表可访问性或缺少free()函数(如果此程序无临界错误自由流):无法将元素添加到单向简单列表中

#include <stdlib.h> 


typedef struct a 
{ 
    a * nast; 
    double v; 

}; 

void add(struct a* list,double d) 
{ 
    list = (a*)malloc(sizeof(a)); 

    if(!list->nast) goto exception; 

    list=list->nast; 

    list->v=d; 

    return; 

exception: 
    printf("Cannot add to the list \n"); 
} 


int main() 
{ 
    struct a l; 

    add(&l,-602.1); 

    return 0; 
} 

的问题是:为什么它扔在list.exe在0x000000013f84107a

未处理的异常: 0000005:访问冲突读取位置0xffffffffffffffff。

运行时错误和如何解决它?

+0

此处:'list =(a *)malloc(sizeof(a));''''你输了很大。你已经放弃了现有的名单(如果有的话)并且无法取回。坐下来思考,直到你明白为什么它不好。然后你会准备好再试一次。 – dmckee

+0

通常更好的方法是使用类型和变量来更加清楚,在您的示例中,您使用“a”作为结构名称和变量名称,如果您在较大的模块中找到这样的代码,会令人困惑。 –

回答

2

这段代码有太多问题,我认为你更多地阅读指针和参数传递会更好。但是这里有几件事情:

  • 在声明中它已经在栈中分配的main功能的“名单”。然后尝试在add函数中重新分配它。

  • 如果要在add函数中分配节点,则需要通过引用传递指针,即指向指针的指针。这是因为否则指针是通过值传递的,并且当函数返回时,指针的所有更改(即实际指针,而不是它指向的内容)都将丢失。

  • malloc函数不会清除分配的内存。如果你想让它自动发生,你应该使用calloc函数。

  • 你不链接节点到列表中,你简单地用(未初始化的)nast指针覆盖列表头。

  • 在结构中使用typedef,但实际上并没有为此typedef定义名称。

  • 请哦,请不要使用goto!它可以使你的代码非常难以阅读和遵循,如果用得很多(而且很多人会认为即使使用一次也是如此)。


如果我这样做,我有我的add功能带到一个指针作为参数的引用,与值一起添加到列表中。然后,我将为该值分配一个新节点,并通过将next指针指向旧列表将其链接到列表中,然后重新分配列表指针以指向新节点。如果通过的列表是NULL,那么只需将列表指向新节点即可。

事情是这样的:

struct node 
{ 
    struct node *next; 
    double  value; 
}; 

void add(struct node **l, const double value) 
{ 
    /* Allocate a new node, use `calloc` to clear the memory automatically */ 
    struct node *n = calloc(1, sizeof(struct node)); 

    /* Set the value of the new node */ 
    n->value = value; 

    /* Is the list non-null? */ 
    if (*l != NULL) 
    { 
     /* Yes, make the `next` pointer point to the old list */ 
     n->next = *l; 
    } 

    /* Make the list point to the new node */ 
    *l = n; 
} 

此功能可以在这样调用:

/* Initialize to `NULL` to mark the list as empty */ 
struct node *list = NULL; 

/* Add two nodes, passing the list pointer by reference */ 
add(&list, 12.34); 
add(&list, 56.78); 

名单现在有两个节点:

  1. 的第一个节点列表包含值56.78
  2. 该secon d列表中包含值12.34
+1

平心而论,这是goto发现少数防守者的极少数用途之一。不过,直到OP可以在他或她的睡眠中免费写出这种代码错误,你可能是对的。 – dmckee

0

这段代码需要很多工作。你会得到一个例外,但是,因为这行:

if(!list->nast) goto exception;

malloc不零出它分配的内存。你分配一个新的列表结构,但是因为它没有被清零,所以它的指针保存垃圾。上述检查失败,并在下一行中,您忽略此垃圾并获取异常。

但是,实际上,即使你修复它,这段代码也需要工作。

+0

这是真的,但忽略了在它之前发生的错误的交易断路器。 – dmckee

+0

什么错误,重新分配列表?这是一个错误,但不是导致异常的那个。 – zmbq

+0

它不会导致异常,但确实会使代码无望地崩溃。尝试修复异常时没有意义,但仍然存在该比例的逻辑错误。 – dmckee

0

因为您的list=list->nast;让列表为空。