我正在学习链接列表,我不理解释放字符串时的行为更改。这是代码:
#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
有人可以解释原因吗?我知道它可能不是多次释放的最有效的代码,但我看到了这种行为,这令我感到困惑。非常感谢您帮助我更好地理解这个概念。
由于
答案 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
。