取消分配void双指针

时间:2016-02-12 00:29:45

标签: c++ memory-management

如何释放void双指针?

deallocate(void** ptr)

这是我试图反对的情况:

char* allocated = (char*)allocate_array(sizeof(char), BUFSIZ,0);

deallocate_array((void**)&allocated);

我需要检查ptr是否为NULL,所以这是我的尝试:

if(ptr != NULL && *ptr != NULL){
      free(*ptr);
}
ptr = NULL;
return;

2 个答案:

答案 0 :(得分:2)

你的尝试非常好。你想要这样的东西:

void deallocate(void **ptr) {
    char *allocated = NULL;
    if (ptr) {
        allocated = *ptr;
    }
    if (allocated) {
        free(allocated);
        *ptr = NULL;
    }
}

你会这样称呼:

deallocate(&allocated);

传入指针地址的原因是,您可以在重新分配后将指针设置回null。

答案 1 :(得分:0)

你可能会使这比需要更复杂。没有理由将地址(例如&allocated)传递给deallocate函数(除非将原始指针的值设置为NULL而不使用回报)。你可以简单地传递一个指针。是的,该函数将接收该指针的副本,但它仍将包含要释放的内存块的起始地址。 e.g:

void deallocate (void *ptr)
{
    if (!ptr) return;
    free (ptr);
}

如果您的意图是解除分配并将原始指针指向的值设置为NULL函数中的deallocate,那么是的,您需要传递原始地址以便设置指向NULL的指针会反映在调用函数中(或者您可以创建函数void *并返回指向值设置为null的指针)。将参数作为deallocate指针传递给void,您可以执行以下操作:

void deallocate_doubleptr (void *ptr)
{
    if (!ptr || !*(void **)ptr) return;
    free (*(void **)ptr);
    *(void **)ptr = NULL;
}

注意:,你没有传递void **参数,你只需传递一个void *(void)指针并根据需要在函数中进行转换。参数是仍然是void指针。)

一个简短的例子说明两者都是等价的,除了NULL的明确赋值,并猜测你的allocate_array会是什么:

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

void *allocate_array (size_t size, size_t nmemb, int set);
void deallocate (void *ptr);
void deallocate_doubleptr (void *ptr);

int main (int argc, char **argv) {

    size_t size  = argc > 1 ? (size_t)strtoul (argv[1], NULL, 10) : 1;
    size_t nmemb = argc > 2 ? (size_t)strtoul (argv[2], NULL, 10) : 128;
    int    set   = argc > 3 ? (int)strtol (argv[3], NULL, 10) : 0;
    char *str = "The quick brown fox jumps over a lazy dog.";

    char *allocated = NULL;

    if ((allocated = allocate_array (size, nmemb, set)))
        printf ("\nsuccessfully allocated '%zu' bytes initialized to '%d' ('%c').\n",
                size * nmemb, set, set);

    if (31 < set && set < 127) { /* if filled with printable ASCII */
        allocated[strlen (str)] = 0;                /* nul-terminate */
        printf ("allocated : '%s'\n", allocated);   /* output array */
    }

    strncpy (allocated, str, size * nmemb - 1);     /* copy str to array */
    allocated[size * nmemb - 1] = 0;                /* nul-terminate */

    printf ("allocated : '%s'\n", allocated);       /* output */

#ifdef DEALLOCDBL
    deallocate_doubleptr (&allocated);
    printf ("deallocated all memeory, pointer reinitialized to 'NULL'\n");
#else
    deallocate (allocated);
    printf ("deallocated all memeory.\n");
#endif

    return 0;
}

void *allocate_array (size_t size, size_t nmemb, int set)
{
    if (!size || !nmemb) {
        fprintf (stderr, "error: invalid size or number of members.\n");
        return NULL;
    }

    void *memptr = NULL;

    if (set != 0) {
        memptr = malloc (nmemb * size);
        memset (memptr, set, nmemb * size);
    }
    else
        memptr = calloc (nmemb, size);

    if (!memptr) {
        fprintf (stderr, "error: virtual memory exhausted.\n");
        exit (EXIT_FAILURE);
    }

    return memptr;
}

void deallocate (void *ptr)
{
    if (!ptr) return;
    free (ptr);
    ptr = NULL;
}

void deallocate_doubleptr (void *ptr)
{
    if (!ptr || !*(void **)ptr) return;
    free (*(void **)ptr);
    *(void **)ptr = NULL;
}

<强>编译

gcc -Wall -Wextra -o bin/allocate_deallocate allocate_deallocate.c

gcc -Wall -Wextra -DDEALLOCDBL -o bin/allocate_deallocate_dbl allocate_deallocate.c

(大多数编译器应采用相同或非常相似的选项)

<强>输出

无论调用的实现如何,输出都是相同的。 (例如allocate_deallocateallocate_deallocate_dbl):

$ ./bin/allocate_deallocate 1 64 65

successfully allocated '64' bytes initialized to '65' ('A').
allocated : 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
allocated : 'The quick brown fox jumps over a lazy dog.'
deallocated all memeory.

内存/错误检查

$ valgrind ./bin/allocate_deallocate 1 64 65

$ valgrind ./bin/allocate_deallocate_dbl 1 64 65

==13759== Memcheck, a memory error detector
==13759== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==13759== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==13759== Command: ./bin/allocate_deallocate
==13759==

successfully allocated '64' bytes initialized to '65' ('A').
allocated : 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
allocated : 'The quick brown fox jumps over a lazy dog.'
deallocated all memeory, pointer reinitialized to 'NULL'
==13759==
==13759== HEAP SUMMARY:
==13759==     in use at exit: 0 bytes in 0 blocks
==13759==   total heap usage: 1 allocs, 1 frees, 64 bytes allocated
==13759==
==13759== All heap blocks were freed -- no leaks are possible
==13759==
==13759== For counts of detected and suppressed errors, rerun with: -v
==13759== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

仔细看看,如果您有任何问题,请告诉我。