链表行为 - 帮助我理解

时间:2013-02-03 09:06:13

标签: c pointers linked-list malloc free

我正在学习链接列表,我不理解释放字符串时的行为更改。这是代码:

#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 个答案:

答案 0 :(得分:2)

您将获得undefined behavior

你正在释放一个内存(auxPtr),但你仍然碰巧有一个指针 - 作为相关节点中的data。这称为dangling reference

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

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

答案 1 :(得分:0)

您不是通过strncpy复制数据字符串 - 而是简单地将指针指向您稍后释放的相同字符串

答案 2 :(得分:0)

如图所示here在释放后访问指针是未定义的行为。

答案 3 :(得分: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