2014-10-16 63 views
0

我已经编写了一个代码,用于从单个链接列表中删除节点a。我测试过这段代码,输出很好。我对这段代码中最后的“else”块有些困惑。这是对的吗? 我的意思是,释放(p-> ptr)节点后,我仍然可以访问它旁边的节点吗?这段代码是否正确地从链表中删除节点?

NODE* delNODE(NODE *HEAD,int position){ 
     int k=1; 
     NODE *p; 
     if(HEAD==NULL){ 
      printf("List Empty\n"); 
      return HEAD; 
     } 

     p=HEAD; 
     if(position==1){ 
      p=HEAD; 
      HEAD=HEAD->ptr; 
      free(p); 
      printf("Success!\n"); 
      return HEAD; 
     } 
     else{ 
      while(k<position-1){ 
       k++; 
       p=p->ptr; 
      } 

      if((p->ptr)==NULL) 
      { 
       printf("NO such position\n"); 
      } 
      else{ 
       free(p->ptr); 
       p->ptr=p->ptr->ptr; 
       printf("Success!\n"); 
      } 
     } 
    return HEAD; 
} 
+0

@pala做同样的情况也会是不正确的。 – 2014-10-16 11:53:10

回答

1

不,这不行。这似乎是“工作”的唯一原因是因为在你尝试过的那些时候,内存分配器已经标记了你已经释放的内存空间,但实际上并没有覆盖它或以其他方式触及它,所以先前值仍然坐在那里的内存地址。你不能指望这总是正确的。例如,如果该节点是特定页面中最后分配的一块内存,则没有什么可以阻止您执行free()将其从进程的虚拟内存表中删除,从而导致您的下一次尝试访问它时出现分段违规。

使用一个临时变量来代替:

NODE * tempnode = p->ptr->ptr; 
free(p->ptr); 
p->ptr = tempnode; 
+0

谢谢!这清除了我的怀疑! – 2014-10-16 11:56:19

0

你不能,也不应该。就像在删除头节点的第二个if语句中一样使用中间变量。

+0

但是当我使用这个函数删除一个节点并打印整个链表时,输出结果是正确的。你能解释为什么吗? – 2014-10-16 11:39:24

+0

@ 2ndGenCore_i5这只是未定义的行为。 – 2501 2014-10-16 11:44:10

+0

感谢您的洞察! – 2014-10-16 11:50:00