c - 关于函数内部的自由指针有点令人困惑

标签 c pointers malloc free

几周前,我了解了如何在函数内部分配和解除分配指针的正确方法,例如 linkedList 中给出的:

typedef struct _node {
    void *data;
    struct _node *next;
} Node;

typedef struct _linkedList {
    Node *head;
    Node *tail;
    Node *current;
} LinkedList;

在我看来,销毁队列的正确方法是使用获取指向我要删除的节点的指针的函数:

void destroy (Node ** node) 

或者在更真实的示例中,指向要删除的指针的指针和指向要删除的列表的指针。

void destroy (LinkedList * list, Node ** node) 

但现在我正在阅读《理解 C 指针》一书,我遇到了问题,因为在第 6 章指向结构的指针中,有以下函数 destroyList 的示例:

void delete(LinkedList *list, Node *node) {
    if (node == list->head) {
        if (list->head->next == NULL) {
            list->head = list->tail = NULL;
        } else {
            list->head = list->head->next;
        }
    } else {
        Node *tmp = list->head;
        while (tmp != NULL && tmp->next != node) {
            tmp = tmp->next;
        }
       if (tmp != NULL) {
            tmp->next = node->next;
        }    
    }   
    free(node);  //free on pointer copy value not pointer
}

因此,在这个示例中,作者在按值传递的指针上自由运行,所以在我看来这不应该起作用。但我查看了勘误表,没有关于此示例的注释。

在这种情况下,我理解 List 是使用列表的正确实例的函数参数,但应该是:

free(list->head) ; //It should work?

然后还为分配的列表释放内存。

我说得对吗?因为读这个例子我有一种感觉,我对这个主题的理解有问题。

我还访问了 Linux 手册页,看到了免费原型(prototype):

 void free(void *ptr);    // http://linux.die.net/man/3/free

那么,为什么当您想要释放内存时,每个人都告诉要传递指针到指针,但在标准库中,相同的 free 函数将指针作为参数而不是指向指针的指针,它如何正确工作?

最佳答案

正如您所说的正确,free( void *p ) 释放 p 指向的内存,但由于地址是按值传递的,因此对于调用者来说它将保持不变。因此你可能会遇到这样的问题:

int *p = malloc( sizeof *p );

*p = 1;
free( p );
...

if( p )
   *p = 2;     // Undefined Behaviour!!! although p is free()'d it's still != NULL

所以你经常会发现

free( p );
p = NULL;

尽管如此,我认为编写一个类似 free() 的函数是可以的,在该函数中按值传递指针,只要函数的描述清楚地表明指针不能 之后使用(无论指针是什么类型)。但是当然,您可以自由地使用双指针定义函数,并将内部所有 free() 的内容设置为 NULL,就像这个非常简单的示例一样:

void myfree( void **pp )
{
   free( *p );
   *p = NULL;
}

...
int *p = malloc( sizeof *p );
...
myfree( &p );
// now p == NULL

关于c - 关于函数内部的自由指针有点令人困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29218271/

相关文章:

将 float 转换为 int 指针并返回 float?

c++ - 为什么声明为指向字符的指针并分配了 2 个字节大小的 String 的大小会被更改?

c++ - 将相同的 key (使用 malloc 创建)添加两次以映射

c - Malloc 的 char 数组有意外的输出

c - 如何在C中跟踪动态内存的大小

c - 为什么\b 在字符串中间使用时会删除在\b 之前写入的一个字符,但在末尾使用时却不会?

c - 无法创建基于基本命令行参数的计算器

c - 替代 Linux 上的 backtrace() 可以找到静态函数的符号

c++ - ARM架构中C函数如何返回大小超过一个字的值

pointers - 如何使用反射读取指向 slice 的指针的值?