【问题标题】:Free a pointer from an external function从外部函数中释放指针
【发布时间】:2015-08-21 05:29:36
【问题描述】:

我编写了一个使用堆栈 ADT 的程序。
main 创建了一个新堆栈,同时为用户提供了 3 个函数供用户使用:

Stack my_stack = sCreate (copy_int, free_int, print_int);

当我调用“窥视”功能时:

printf ("Peek: |%d|\n\n", *(int*)sPeek(my_stack));

我有内存泄漏。

peek 函数如下所示:

Element sPeek (Stack stack){
if ((NULL == stack) || (0 >= stack->used_places))
    return NULL;

Element returnElement = stack->copy_function(stack->stack_array[stack->used_places-1]);
if (NULL == returnElement){
    free (returnElement);
    return NULL;
}   
return returnElement;

这可能是由那里调用的copy_function引起的,也就是用户给的copy_int:

Element copy_int (Element element){
int *new_int = (int*) malloc(sizeof(int*));
*new_int = *(int*)element;
if (NULL != new_int)
    return new_int;
else
    return NULL;

如何从 copy_int 释放指针(malloc)?

【问题讨论】:

  • 与您的问题没有直接关系,但您真的认为为一个 int 指针 (malloc(sizeof(int*))) 分配空间是个好主意吗?
  • 你是否建议在堆栈上做同样的事情?我的意思是没有malloc?
  • 尽可能不要使用malloc,在这种情况下,你根本不需要malloc,你可以简单地返回int而不使用malloc:@987654329 @
  • 您的 peek 原语不应复制任何内容。窥视的意思。你不会复制你想看的东西。 Push 应该复制,pop 应该释放。或者,如果您确实想制作一份副本以供查看,则用户有责任在使用后对其进行清理。
  • 同时告诉您的用户他们的copy_int 是错误的。数数你的星星:Type <n stars> name = malloc(nelems * sizeof(Type <n-1 stars>))。简单!并且不要强制转换 malloc 的 rwturn 值。

标签: c pointers malloc


【解决方案1】:
Element e = sPeek(my_stack);
if (e) {
    printf ("Peek: |%d|\n\n", *(int*)e);
}
free(e);

似乎有点明显,所以不确定是不是你的意思。

【讨论】:

    【解决方案2】:

    在最后一个代码 sn-p 中,您在检查来自 malloc 的返回值之前使用了 *new_int。如果new_intNULL,这将导致分段错误。此外,if/else 在书面上完全没有价值。这四行可以替换为return new_int;,在任何情况下都不会改变行为。最后,don't cast the return value from malloc

    所有这些问题都解决了,最后的代码 sn-p 看起来像这样

    Element copy_int (Element element)
    {
        int *new_int = malloc(sizeof(int));
        if ( new_int )
            *new_int = *(int*)element;
        return new_int;
    }
    

    sPeek 函数中,您有一个类似的毫无价值的if 语句。如果returnElementNULL,则free 没有任何内容。所以sPeek函数应该是

    Element sPeek (Stack stack)
    {
        if ( stack && stack->used_places > 0 )
            return stack->copy_function(stack->stack_array[stack->used_places-1]);
        else
            return NULL;
    }
    

    最后,对于您的问题,copy_int 返回的内存 将被泄漏,除非您保留该指针的副本,并在您完成后使用 free 它。此外,如果您将 NULL 指针传递给printf,您将要求另一个分段错误。所以printf这一行需要替换成这段代码(假设Element真的是void *

    int *value = sPeek(my_stack);
    if (value)
        printf ("Peek: |%d|\n\n", *value);
    free(value);
    

    【讨论】:

    • 您的回答“解决了”我的问题。我使用了 2 个修复程序,并且代码更少,效果很好。
    【解决方案3】:

    如何从 copy_int 释放指针(malloc)?

    如果您不再需要它,只需拨打free()即可。


    这里也有

    int * new_int = (int*) malloc(sizeof(int*));
    *new_int = *(int*)element;
    if (NULL != new_int)
      return new_int;
    else
      return NULL;
    

    NULL 的测试应该在取消引用指针 element 之前完成:

    int *new_int = malloc(sizeof(int*));
    if (NULL != new_int)
    {
      *new_int = *(int*)element;
      return new_int;
    }
    else
      return NULL;
    

    注意:在 C 中不需要转换 malloc/calloc/realloc 的结果,也不建议以任何方式进行。


    另外^2 在这里调用free()

    if (NULL == returnElement){
      free (returnElement);
      return NULL;
    }
    

    使用较少,因为free() 没有任何东西,因为returnElement 指向无处b 携带NULL。你想删除它。

    【讨论】:

      【解决方案4】:

      任何返回资源的函数在使用后不会自动释放,必须有文档说明如何释放资源。对于malloc(),它被记录为free(),对于fopen(),它是fclose()等等。

      当你自己创建一个函数时,你可以例如如果您返回一个又从malloc() 收到的指针,请参考free()。如果您有更复杂的设置,您可能需要创建自己的函数。

      查看您的函数,您使用malloc() 分配内存,然后分配给内存(或者如果分配失败,您验证为时已晚),然后准确返回从malloc() 接收的指针。因此,您返回的资源可以(并且必须!)通过free() 释放。

      顺便说一句:考虑不要不必要地复制内容。您对copy_int() 的调用对我来说似乎是多余的,只需返回一个指向 const int 的指针,引用现有元素,就可以了。

      【讨论】:

        猜你喜欢
        • 2022-06-14
        • 2011-08-28
        • 1970-01-01
        • 2013-10-20
        • 2022-01-07
        • 1970-01-01
        • 1970-01-01
        • 2015-03-04
        • 2012-08-07
        相关资源
        最近更新 更多