関数呼び出し内の Malloc は戻り時に解放されるように見えますか?

StackOverflow https://stackoverflow.com/questions/105477

  •  01-07-2019
  •  | 
  •  

質問

最も基本的なケースまでは理解できたと思います。

int main(int argc, char ** argv) {
  int * arr;

  foo(arr);
  printf("car[3]=%d\n",arr[3]);
  free (arr);
  return 1;
}

void foo(int * arr) {
  arr = (int*) malloc( sizeof(int)*25 );
  arr[3] = 69;
}

出力は次のとおりです。

> ./a.out 
 car[3]=-1869558540
 a.out(4100) malloc: *** error for object 0x8fe01037: Non-aligned pointer
                         being freed
 *** set a breakpoint in malloc_error_break to debug
>

私の理解が間違っている箇所を誰かが明らかにしていただければ、大変感謝いたします。

役に立ちましたか?

解決

ポインタは参照ではなく値で渡されるため、foo 内で arr を使って何をしても、foo 関数の外側では違いが生じません。m_pGladiator が書いたように、1 つの方法は、このようにポインターへの参照を宣言することです (ちなみに、C++ でのみ可能です)。C は参照について知りません):

int main(int argc, char ** argv) {
  int * arr;

  foo(arr);
  printf("car[3]=%d\n",arr[3]);
  free (arr);
  return 1;
}

void foo(int * &arr ) {
  arr = (int*) malloc( sizeof(int)*25 );
  arr[3] = 69;
}

別の (より良い個人的な) 方法は、ポインタを引数として渡すのではなく、ポインタを返すことです。

int main(int argc, char ** argv) {
  int * arr;

  arr = foo();
  printf("car[3]=%d\n",arr[3]);
  free (arr);
  return 1;
}

int * foo(void ) {
  int * arr;
  arr = (int*) malloc( sizeof(int)*25 );
  arr[3] = 69;
  return arr;
}

また、ポインタをポインタに渡すこともできます。これが参照渡しの C の方法です。構文は少し複雑ですが、まあ、C はそういうものです...

int main(int argc, char ** argv) {
  int * arr;

  foo(&arr);
  printf("car[3]=%d\n",arr[3]);
  free (arr);
  return 1;
}

void foo(int ** arr ) {
  (*arr) = (int*) malloc( sizeof(int)*25 );
  (*arr)[3] = 69;
}

他のヒント

foo に arr を割り当てましたが、そのポインター値は呼び出しスタックに格納されます。これを実行したい場合は、次のように実行します。

void foo( int ** arr) {
    *arr = (int *)malloc( sizeof(int) * 25 );
    (*arr)[3] = 69;
}

そして main では、単純に foo へのポインタを渡します (foo(&arr) のように)。

foo は int ポインタのローカル コピーを受け取り、それにメモリを割り当て、スコープ外に出るとそのメモリをリークします。

これを修正する 1 つの方法は、foo にポインターを返すようにすることです。

int * foo() {
  return (int*) malloc( sizeof(int)*25 );
}

int main() {
    int* arr = foo();
}

もう 1 つは、foo にポインターをポインターに渡すことです。

void foo(int ** arr) {
   *arr = malloc(...);
}

int main() {
    foo(&arr);
}

C++ では、ポインターへの参照を受け入れるように foo を変更する方が簡単です。C++ で必要な唯一の変更は、foo を次のように変更することです。

void foo(int * & arr)

ポインタを値で渡しているため、main 内の arr ポインタは割り当てられたメモリを指していません。これは次の 2 つのことを意味します。メモリ リークが発生しており (いいえ、関数 foo が完了してもメモリは解放されません)、main 内の arr ポインタにアクセスすると、メモリの任意の範囲にアクセスすることになるため、3 が出力されません。 out であるため、free() は機能しません。main 内の arr[3] にアクセスするときにセグメンテーション違反が発生しなかったのは幸運でした。

引数 (arr) が参照 (&) によって渡されない場合、その値を変更することはできません。一般に、ポインタを返す必要があるため、メソッドは次のようになります。

arr=foo();

引数を再割り当てしようとするのは悪い判断です。(&) ソリューションはお勧めしません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top