1

我正在学习链表,我不明白释放字符串时的行为变化。这是代码:

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

struct node {
    char*          data;
    struct node*   next;
    };

void Push(struct node** headRef, char *data)
{
    struct node* newNode = malloc(sizeof(struct node));
    newNode->data = data;
    newNode->next = *headRef;  // The '*' to dereferences back to the real head
    *headRef = newNode;        // ditto
}

int main(int argc, const char * argv[])
{

    char* auxStr;
    struct node* list;
    struct node* auxPtr;
    int i=5;


    while (i<9)
    {
        auxStr=malloc(sizeof("String:%d"));
        sprintf(auxStr, "String:%d",i);
        Push(&list, auxStr);
        i++;
    }

    auxPtr=list;

    i=0;
    while (auxPtr)
    {
        printf("Node:%d - Data:%s\n",i++,auxPtr->data);
        auxPtr=auxPtr->next;
    }

    return 0;
}

这导致:

Node:0 - Data:String:8
Node:1 - Data:String:7
Node:2 - Data:String:6
Node:3 - Data:String:5

现在,当我第一次添加 free(auxStr) 时:

while (i<9)
{
    auxStr=malloc(sizeof("String:%d"));
    sprintf(auxStr, "String:%d",i);
    Push(&list, auxStr);
    free(auxStr);
    i++;
}

我现在得到:

Node:0 - Data:String:8
Node:1 - Data:String:8
Node:2 - Data:String:8
Node:3 - Data:String:8

有人可以解释为什么吗?我知道它可能不是最有效的代码释放多次,但我看到了这种行为,这让我感到困惑。感谢您的帮助,以帮助我更好地理解这个概念。

谢谢

4

4 回答 4

2

你得到未定义的行为

您正在释放内存 ( auxPtr) 但您仍然碰巧有一个指向它的指针 - 就像data在相关节点中一样。这称为悬空引用

这些数据会发生什么是未定义的,它恰好为每个新分配重用相同的地址(但同样,任何事情都可能发生)。

因此,稍后打印数据时 - 输出未定义。

于 2013-02-03T09:10:17.240 回答
0

您不是通过 strncpy 复制数据字符串 - 相反,您只是将指针分配给稍后释放的相同字符串

于 2013-02-03T09:10:59.463 回答
0

here所示,在释放它后访问一个指针是未定义的行为。

于 2013-02-03T09:11:13.650 回答
0

您的每个数据都struct node指向同一地址。释放时auxPtr,您正在访问一个不再分配的内存位置。在 C 中,它会导致未定义的行为。动态分配数据可能是一个更好的主意,如下所示。

#include <assert.h>
#include <stdlib.h>
#include <string.h>

void Push(struct node **head, const char *data, size_t size)
{
  struct node *elt;

  elt = malloc(sizeof *elt);
  assert(elt != NULL);

  elt->data = malloc(size);
  assert(elt->data != NULL);
  memcpy(elt->data, data, size);

  elt->next = *head;
  *head = elt;
}

此外,您的列表中没有空指针。你应该先分配list

于 2013-02-03T09:11:52.633 回答