【问题标题】:memory allocation - call by reference String-Array-Paramater内存分配 - 通过引用 String-Array-Parameter 调用
【发布时间】:2013-11-10 01:23:57
【问题描述】:

问题是在这个例子中如何正确分配/释放内存:

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”)。为什么?它将如何运作?

【问题讨论】:

  • 不适用于你的问题,但不要强制转换 malloc() 的返回值
  • 测试中的array[0] 与测试之外的array[0] 不同。在 test 中,array 保存了函数调用 test 中名为 array 的变量的地址。还有do not cast the return value of malloc
  • 我认识到这是两个不同的数组[0](仍然不明白为什么),但是我如何才能释放分配的内存?
  • 另注:strlen 不包含 '\0' 字符。
  • 这是什么while (...)

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


【解决方案1】:

代替

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

【讨论】:

  • 感谢您的回答 - 仍然是同样的问题...无法释放函数外的内存
  • 谢谢你,你的示例代码在这里也可以工作......但我太愚蠢了,看不出与我的区别。
  • @claptrap 您不需要将 i 初始化为 0,for 会为您完成。
  • @Eregrith 我知道,这是一种反射 ;-)
  • 是的,我不能怪你^^
【解决方案2】:

针对您的特定问题:

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

要释放它,从i = 0 循环到i &lt; 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 返回后,您将无法释放分配的内存。

【讨论】:

  • 感谢您的长回答,但这并不能解决我的问题。
  • 它如何不处理您的问题?你至少看过我回答的第一部分吗?
  • 我的问题是引用分配,我无法再次释放它。你的第一个例子:所有东西都在同一个功能中。第二个例子:返回值。没有通过引用调用。
  • C 中没有“引用”之类的东西。传递给函数的是变量array 的地址,您将malloc 的内存地址存储在那里,其中您存储其他 malloc 的内存地址。您必须首先释放包含在第一个分配的内存块中的指针,这是您的数组“单元格”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-22
  • 1970-01-01
  • 2015-08-16
  • 2016-12-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多