Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 释放链表节点时出现分段错误_C++_Pointers_Null_Segmentation Fault_Free - Fatal编程技术网

C++ 释放链表节点时出现分段错误

C++ 释放链表节点时出现分段错误,c++,pointers,null,segmentation-fault,free,C++,Pointers,Null,Segmentation Fault,Free,这是一个删除下一个点节点的函数,逻辑简单。当前代码运行良好。但是如果我取消注释注释行,就会出现分段错误,这在我看来很奇怪。提前感谢。这是一个错误的实现。如果L->next为空怎么办 以下是一种可能的(正确的)实现: LNode * deleteNext (LNode *L) { if (L == NULL) { return L; } LNode *deleted = L->next; L->next = L->next->next; //L->n

这是一个删除下一个点节点的函数,逻辑简单。当前代码运行良好。但是如果我取消注释注释行,就会出现分段错误,这在我看来很奇怪。提前感谢。

这是一个错误的实现。如果
L->next
为空怎么办

以下是一种可能的(正确的)实现:

LNode * deleteNext (LNode *L) {
  if (L == NULL) { return L; }

  LNode *deleted = L->next;
  L->next = L->next->next;
  //L->next->next = NULL;

  delete deleted;
  return L->next;
}

现在由您决定您希望从函数返回什么。您可以返回
L
而不是
L->next
,也可以返回包含
L
std::pair
和一个指示是否完成删除的布尔值。

这都取决于列表的头和尾是如何实现的。我将假设列表的最后一个元素的下一个链接设置为null(即列表本身不是一个闭合环)

这一呼吁在概念上是错误的。除非将第一个元素用作标题,否则在处理单个链接列表时,必须保留对其标题(第一个元素)的引用,这既丑陋又低效

您还必须决定如何处理删除的元素。删除它,然后返回一个指向它仍然温暖的尸体的指针,无论如何都不是最好的选择

我将假设调用方在检索元素时可能受到干扰(在这种情况下,调用方必须在使用完元素后将其删除)

这将无法完全清空列表。至少有一个元素会留在其中(可以说是伪头)

您还必须使用所述伪头初始化列表。使用伪头调用removeNext是安全的,它将等同于使用列表作为后进先出。 不过,这种实现不允许作为FIFO轻松使用,因为没有简单的方法来维护对列表尾部(最后一个元素)的固定引用

我会这样做:

LNode * removeNext (LNode *L)
{
  if (L == NULL) panic ("Caller gave me a null pointer. What was he thinking?");
  // should panic if the caller passes anything but a valid element pointer,
  // be it NULL or 0x12345678

  LNode * removed = L->next;
  if (removed = NULL) return NULL; // L is the end of list: nothing to remove
  L->next = removed->next; // removed does exist, so its next field is valid

  // delete removed; // use this for the void deleteNext() variant
  return removed;
}
(我早在90年代中期就写了这篇文章。真正的复古ANSI C。啊,那些日子…)

归结起来就是:如果你要实现一个单链表,不要试图把它当作一个随机访问的数据结构来使用。它充其量是低效的,而且常常是一窝臭虫。单个链表可以用作FIFO,也可以用作堆栈,仅此而已


std::templates为您提供了存储结构方面的一切梦想,在过去20年左右的时间里,它们经过了测试和优化。没有一个活着的人(可能除了唐纳德·克努斯)能用从头开始的设计做得更好。

如何调用该函数?(作为L传递什么?)你检查L是否为空,但如果为空,你不检查L->next或L->next->next。@Vladp很高兴你问,PRAM可能是链接列表中除尾部节点以外的所有节点。如果
L->next->next
NULL怎么办?@FredrickGauss:在这种情况下,函数返回
NULL
(即
L->next
return
处将
NULL
)。谢谢两位。很抱歉没有提到输入。实际上输入可能总是正确的,我的意思是,没有L->next为空的情况。L->next->next可以为空,除非它是尾部节点,其下一个将始终为空,所以它是安全的。@Briyanyang:错误的输入仍然是函数的责任。因此函数必须检查
L->next==NULL
@Nawaz谢谢,明白了。根据我对这个函数的逻辑,它应该不会错。我的意思是,对于那个注释行。非常有趣。尤达说。请原谅我的法语,年轻学徒。英语我的母语不是;)。
LNode * removeNext (LNode *L)
{
  if (L == NULL) panic ("Caller gave me a null pointer. What was he thinking?");
  // should panic if the caller passes anything but a valid element pointer,
  // be it NULL or 0x12345678

  LNode * removed = L->next;
  if (removed = NULL) return NULL; // L is the end of list: nothing to remove
  L->next = removed->next; // removed does exist, so its next field is valid

  // delete removed; // use this for the void deleteNext() variant
  return removed;
}
typedef struct _buffer {
   struct _buffer * next;
   unsigned long    data;
   } tBuffer;

typedef struct {
   tBuffer * head;
   } tLIST; 

/* ---------------------------------------------------------------------
   Put a buffer into a list
   --------------------------------------------------------------------- */
static void list_put (tLIST * mbx, tBuffer * msg)
{
   msg->next = mbx->head;
   mbx->head = msg;
}

/* ---------------------------------------------------------------------
   get a buffer from a list
   --------------------------------------------------------------------- */
static tBuffer * list_get (tLIST * mbx)
{
   tBuffer * res;

   /* get first message from the mailbox */
   res = mbx->head;

   if (res != NULL)
      {
      /* unlink the buffer */
      mbx->head = res->next;
      }

   return res;
}