1

问题是如何在此示例中正确分配/释放内存:

void test(char*** array, int* count) {

  *array = malloc(sizeof(char*) * MAX_ARRAY);
  while (...) {
    (*array)[i] = (char*)malloc(strlen(fooString));
  }
}

函数调用:

char** array;
int count;
test(&array, &count);
// now free the memory - i think i have to?
for(i = 0; i < count; i++) {
  free(array[i]); // <-- crash here
}
free(array);

看起来 array[0] 在测试函数内部的地址与外部不同。怎么会这样?看起来我误解了某事,因为数组的地址在函数内部和外部是相同的。

编辑:问题是我无法释放分配的内存(参见代码中的“crash here”)。为什么?它将如何运作?

4

2 回答 2

2

代替

void test(char*** array, int* count) {

  *array = malloc(sizeof(char*) * MAX_ARRAY);
  while (...) {
    (*array)[i] = (char*)malloc(strlen(fooString));
  }
}

void test(char*** array, int count) {

  *array = malloc(sizeof(char*) * count); // number of pointers
  for (int i = 0; i < count; ++i) 
  {
    (*array)[i] = malloc(strlen(fooString)); 
  }
}

虽然我不确定是什么fooString,因为你没有显示 decl/def。通常你会为 \0 分配一个额外的字节

(*array)[i] = malloc(strlen(fooString) + 1)

这似乎有效

#include <stdio.h>
#include <inttypes.h>
#include <malloc.h>
#include <string.h>

char fooString[256];

void test(char*** array, int count) 
{
  int i = 0;
  *array = malloc(sizeof(char*) * count);
  for (i = 0; i < count; ++i) 
  {
    (*array)[i] = malloc(strlen(fooString)+1);
  }
}

int main()
{
  char** array = NULL;
  int count = 100;
  int i = 0;
  test(&array, count);


  for(i = 0; i < count;++i) 
  {
    free(array[i]); 
  }
  free(array);    
  return 0;
}
于 2013-10-30T13:17:08.550 回答
0

对于您的特定问题:

您分配(*array)[i]which is a char*to strlen(fooString)which 通常相当于sizeof(char) * strlen(fooString): 这很容易出错。您应该sizeof(*((*array)[i]))在这种情况下使用以确保不会错过正确的类型。

要释放它i = 0,从to循环i < MAX_ARRAY并调用free(array[i]) What you put in place ...in your code 非常重要

一般来说,在分配内存时,一定要尊重这些一般的想法:

  • 如果一个函数分配内存,它会自行释放它,除非在之后需要它时。
  • 如果一个函数在之后分配外部所需的内存,它就是这样做的。

这允许更好的代码架构和更容易释放内存。

例如:

第一点:

void foo()
{
  char *a;

  a = malloc(sizeof(*a) * 5);
  a[0] = 'a';
  a[1] = 'b';
  a[2] = 'c';
  a[3] = 'd';
  a[4] = 0; //or '\0' if you prefer
  do_something_cool(a);
  free(a);
}

该函数foo分配内存、处理它并释放它。

第二点:

char *halfstrdup(char *str)
{
  int len;
  int i;
  char *newstr;

  len = strlen(str);
  newstr = malloc(sizeof(*newstr) * len / 2)
  for (i = 0; i < len; i++)
  {
    if ((i % 2) == 0)
      newstr[i / 2] = str[i];
  }
  return (newstr);
}

void foo2()
{
  char *half;

  half = halfstrdup("Hello, world !");
  do_something_cooler(half);
  free(half);
}

该函数halfstrdup只是分配和设置您需要的内存并返回它,该函数foo2通过使用分配内存halfstrdup,然后使用它并释放它。

不要忘记在丢失指针之前释放,例如从 foo 或 foo2 返回后,您将无法释放分配的内存。

于 2013-10-30T13:16:29.117 回答