C在函数内部使用malloc

C usage of malloc inside a function

我有以下功能:

char * decrypt(const char *p, int key) {
  char *tmp = malloc(strlen(p) + 1);
  for (int i = 0; p[i] != '[=10=]'; i++) {
    if (p[i] >= 'A' && p[i] <= 'Z') {
      if (key <= p[i] - 'A')
        tmp[i] = p[i] - key;
      else
        tmp[i] = p[i] - key + 'Z' - 'A' + 1;
    } else if (p[i] >= 'a' && p[i] <= 'z') {
      if (key <= p[i] - 'a')
        tmp[i] = p[i] - key;
      else
        tmp[i] = p[i] - key + 'Z' - 'A' + 1;
    }
  }
  return tmp;
}

我正在为临时指针 *temp 分配内存:

char *tmp = malloc(strlen(p) + 1);

但我不会在任何地方释放它。

据我所知,释放该内存有 4 个选项:

  1. 在同一范围内使用 free()(这对我来说是不可能的,因为我必须 return 指针)
  2. 使用 alloca() 并非每个编译器都支持(非 ANSI C)
  3. malloc() 函数外部的指针并将该指针传递给函数,然后 free() 它在函数外部
  4. 将 returned 指针分配给一个变量并释放该变量

这是选项 #4 的代码:

char *var;
var = malloc(MAX);
var = decrypt("Hello", 1);
free(var);

当我为它分配一个 returned 指针时,我是否必须 malloc() 变量 var,因为该指针已经 malloc()ed?

我的问题是:

在函数内部使用 malloc() 的最佳方式是什么?

如果我选择第 4 个选项,我是否必须先 malloc() 变量,然后再为它分配 returned 指针?

应该是:

char *var = decrypt(whatever);
// ...use var...
free(var);

我不知道你为什么要在你的代码示例中事先泄漏一些内存。

您的计划 (3) 预先分配内存并让函数填充它也是可行的,但它会导致代码更冗长,因为它引入了函数导致缓冲区溢出的可能性。

alloca 不起作用,因为 space 在函数 returns.

时被释放

您可以修改 decrypt 函数的签名,使其提供函数写入结果的指针。

void decrypt(char* dest, const char *p, int key);

这样,调用者全权负责管理此内存space。

问:在函数内部使用 malloc() 的最佳方式是什么?

答:如果你真的想在函数内分配内存(就像现在这样),你必须在这个函数外释放内存(也许与其他互补函数)。有时人们为这些函数使用特殊的名称(例如 decrypt_ma() 而不是 decrypt())来记住内存分配的事实。

问:如果我要使用第 4 种方式,我是否必须先 malloc() 该变量,然后再将其分配给 returned 指针?

A:如果在调用 decrypt() 之前分配内存,decrypt() 根本不应该 return 指针(您将使用 [=14 进行所有操作=] 函数体中不应该是 const).

一个简单的替代方法是就地修改字符串:

void decrypt(char *p, int key) {
    for (; *p; p++) {
        if (*p >= 'A' && *p <= 'Z') {
            if (key <= *p - 'A')
                *p -= key;
            else
                *p += ('Z' - 'A' + 1) - key;
        } else
        if (*p >= 'a' && *p <= 'z') {
            if (key <= *p - 'a')
                *p -= key;
            else
                *p += ('Z' - 'A' + 1) - key;
        }
    }
}

请注意,您可以使用 256 字节数组编写更简单、更高效的实现。