Функция, чтобы сделать узел связанного списка к последнему узлу? - PullRequest
1 голос
/ 30 июля 2011

Эта функция возьмет определенный узел связанного списка и сделает его Последним узлом.

void lastNode(struct list *node)
{
  struct list* temp = node->next;
  node->next = NULL;
  struct list* temp2;
  while(temp)
    {

      temp2 = temp->next;
      printf("%p \n",temp);
      free(temp);
      temp = temp2;
    }

}

int main()
{
  struct list d={4,NULL};
  struct list c={3,&d};
  struct list b={2,&c};
  struct list a={1,&b};


  struct list *node = &a;

  lastNode(&b);

  while(node)
    {
      printf("%d \n",node->d);
      node=node->next;
    }
  return 0;
}

но это дает мне ошибку при освобождении узла.

Ответы [ 2 ]

1 голос
/ 30 июля 2011

Глядя на ваш полный код:

struct list c={3,&d};
struct list b={2,&c};

lastNode(&b);

Это не разрешено free temp, поскольку оно не было выделено с помощью malloc.

struct list* temp = node->next; /* temp is now &c. You can't free it. */
while(temp)
{
    /* ... */  
    free(temp); /* Tries to free &c which is on the stack. */
}
1 голос
/ 30 июля 2011

Обновление: Это было написано до того, как был предоставлен вызывающий объект free. Теперь, когда я вижу это, я бы сказал, что да, вы не можете вызвать free для стекового адреса. Однако мой оригинальный ответ сохранился ниже, о том, как лучше сделать удаление списка ...


Я не вижу внезапной ошибки free, но .... кажется, что этот подход будет работать, только если переданный node является первым узлом. Если это какой-то другой узел, кроме первого, вам понадобится указатель на предыдущий, чтобы вы могли установить prev->next = node->next.

На самом деле, думая об этом больше ... Если все, что вы делаете - это берете узел и делаете его последним, зачем вам нужно free что-нибудь? Похоже, этот код освобождает весь список, начиная с temp. Если это ваше намерение, я рекомендую что-то более похожее на это:

void free_all_at_node(struct list **list, struct list *node_to_free)
{
   struct list *n = *list, *prev = NULL;

   // Search for node_to_free, updating prev to indicate the last node we saw.
   //
   while (n && n != node_to_free)
   {
      prev = n;
      n = n->next;
   }

   // Check to see if we found it...
   //
   if (n == node_to_free)
   {
      // Do we have a previous node?
      //
      if (prev)
      {
         // Yes, update next pointer...
         //
         prev->next = NULL;
      }
      else
      {
         // This is the start of the list.  Update the head...
         //
         *list = NULL;
      }

      // Now free stuff...
      //
      while (n)
      {
         struct list *next = n->next;
         free(n);
         n = next;
      }
   }
}

Предполагается, что вы хотите, чтобы node_to_free был первым освобожденным узлом, и, следовательно, мы ищем его по началу списка. Другая альтернатива заключается в том, чтобы вызывающая сторона указывала узел до первого свободного узла. (Похоже, ваш код на самом деле пытается это сделать ...) Я мог бы предпочесть сделать это так:

void free_after_node(struct list *n)
{
   // If the node is NULL or has no next node, there is nothing to do.
   //
   if (n && n->next)
   {
      // Start at the node after the first, since we want to keep the first
      // one around.
      //
      n = n->next;

      // Now free...
      //
      while (n)
      {
         struct list *next = n->next;
         free(n);
         n = next;
      }
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...