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] のアドレスは、test-function の内部と外部のアドレスが異なるようです。どうすればいいの?配列のアドレスは関数の内外で同じなので、sthを誤解しているようです。

編集:問題は、割り当てられたメモリを解放できないことです(コードの「ここでクラッシュ」を参照)。なんで?そして、それはどのように機能しますか?

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

fooStringdecl/def を表示しないため、何が何であるかはわかりませんが。通常、\0 には 1 バイト余分に割り当てます。

(*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]char*を割り当てます。これはエラーが発生しやすくなります。この場合、正しいタイプを見逃さないように使用する必要があります。strlen(fooString)sizeof(char) * strlen(fooString)sizeof(*((*array)[i]))

それを解放するには、ループしi = 0て toi < 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は、メモリを割り当て、処理し、解放します。

2 番目のポイント:

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 に答える