【问题标题】:function to clear malloc, and make pointer to null清除malloc的函数,并使指针指向null
【发布时间】:2020-03-07 15:41:38
【问题描述】:

在我的last question 中,我询问了如何使用函数来释放一个 malloc 的数组,我想改进我的代码,以便该函数不仅会释放内存,还会将指针设置为 @ 987654322@一旦完成清理。 此外,我想要一个函数来同时执行 - 设置和清除,这取决于我传递的 command,这就是我到目前为止所做的:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint-gcc.h>

char **set_arr(int number, char *command);
int command_read(char *command);
void clear_arr(char *arr[], int size);

char set[] = "set";
char clear[] = "clear";

int main() {
    int num = // get number from user;
    char** my_arr = NULL;
    my_arr = set_arr(num, set);
    // so far the code works as excepted
    set_arr((size_t)&my_arr, clear);
    return 0;
}

int command_read(char *command) {
    if (strcmp(command, set) == 0)
        return 'S';
    if (strcmp(command, clear) == 0)
        return 'C';
}

char **set_arr(int number, char *command) {
    static char **arr = NULL;
    static int size;
    switch (command_read(command)) {
      case 'S':
        size = (int)number;
        arr = malloc((size + 1) * sizeof(char *));
        for (int i = 0; i <= size; i++) {
            arr[i] = NULL;
            if (i == size)
                break;
            arr[i] = malloc((string_len) * sizeof(char));
        }
        break;
      case 'C':
        clear_arr(arr, size);
        free(arr);
        uintptr_t value = number;
        uint64_t *temp = (void *)value;
        *temp = 0x0;
        break;
    }
    return arr;
}

void clear_arr(char *arr[], int size) {
    for (int i = 0; i < size; i++) {
        free(arr[i]);
        arr[i] = NULL;
    }    
}

我知道有更好的方法来清除(并分配内存?)但我的主要问题是,我是否释放了为数组分配的所有内存,并且在清除后,指针 my_arr 是否设置正确到NULL?

【问题讨论】:

  • 将一个指向size_t 的指针传递给int 至少不是一个好主意。包含指针可能还不够,也不需要它。

标签: c pointers malloc


【解决方案1】:

在标准 C 中编写通用函数来实现您的目标是不可能的,因为指向不同类型对象的指针可能具有不同的表示,因此您不能传递指针的地址并期望函数以通用方式处理它。

然而,C 标准中的这一规定并未在当今大多数当前系统中使用。特别是,POSIX 标准要求所有指针具有相同的表示。因此,您的通用函数可以在这些系统上运行,并采取一些预防措施来避免编译警告:

// free an array of allocated things
void free_array(void ***p, size_t count) {
    void **array = *p;
    for (size_t i = 0; i < count; i++) {
        free(array[i]);
        array[i] = NULL; // for safety
    }
    free(array);
    *p = NULL;
}
// deal with the non portable conversion with macros
#define FREE_ARRAY(p, n)   free_array((void ***)(void *)&(p), n)

// allocate an array of pointers to allocated things of size `size`.
// return a pointer to the array or `NULL` if any allocation failed
void **malloc_array(size_t count, size_t size) {
    void **array = malloc(count * sizeof(*array));
    if (array) {
        for (size_t i = 0; i < count; i++) {
            array[i] = calloc(size, 1);  // allocate and initialize to all bits zero
            if (array[i] == NULL) {
                while (i-- > 0) {
                    free(array[i]);
                    array[i] = NULL;
                }
                return NULL;
            }
        }
    }
    return array;
}
#define MALLOC_ARRAY(n, type)  ((type **)(void *)malloc_array(n, sizeof(type)))
#define MALLOC_2D_ARRAY(n1, n2, type)  ((type **)(void *)malloc_array(n1, (n2) * sizeof(type)))

将命令作为字符串传递是非常低效的。您应该使用intenum 作为命令,但您可以通过这种方式在程序中使用上述宏和代码:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint-gcc.h>

int main() {
    int string_len = 100;
    int num = 10; // get number from user;
    char **my_arr = MALLOC_2D_ARRAY(num, string_len, char);
    FREE_ARRAY(my_arr, num);
    return 0;
}

【讨论】:

  • 如果你在它们被释放之前将它们清空(因为如果分配了自动或显式释放的范围),你显然不关心效率。
  • @Deduplicator:在此回复中,重点不在于效率,否则我建议不要使用间接伪二维数组。确实没有必要在释放的数组中设置指向NULL 的指针,我只是为了说明而这样做。与free 无论如何都需要更新堆相比,将指针设置为NULL 的开销相对较小。
  • 感谢您的评论,但对我来说这似乎很复杂,因为我在 C 方面没有那么先进,而且英语不是我的第一语言(没有帮助,我什至无法写此评论语法),我会发现自己有更多时间阅读和理解你在这里写的东西。总的来说,感谢您抽出时间给出如此详细的回复:)
  • 以上评论是对 Deduplicator 的回应,他建议我删除一些冗余代码,因为我写了关于效率的评论。你可以无视这一点。恐怕我的回答对于您的问题来说有点太高级了,它实现了一个通用分配器,而您可能只需要处理 char 数组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多