内存分配 - 通过引用调用String-Array-Parameter

时间:2013-10-30 12:53:51

标签: c arrays function memory pass-by-reference

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

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]在test-function中的地址与外部不同。怎么会这样?看起来我误解了,因为数组的地址在函数内部和内部是相同的。

编辑:问题是我无法释放已分配的内存(请参阅&#34;在此处崩溃&#34;在代码中)。为什么?它将如何运作?

2 个答案:

答案 0 :(得分:2)

而不是

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

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

DO

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;
}

答案 1 :(得分:0)

针对您的特定问题:

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

要释放,请从i = 0循环到i < MAX_ARRAY并致电free(array[i]) 您在代码中代替...的内容非常重要

一般,在分配内存时,请务必尊重以下一般想法:

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

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

例如:

第一点:

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返回后,您将无法释放已分配的内存。