16

私はそれを最も基本的なケースに落とし込んだと思います:

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
>

私の理解がどこで失敗しているのかを誰かが明らかにすることができれば、それは大いにありがたいです。

4

5 に答える 5

47

ポインターは参照ではなく値で渡すため、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;
}
于 2008-09-19T20:48:17.473 に答える
6

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

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

そして主に、fooへのポインタを渡すだけです(foo(&arr)のように)

于 2008-09-19T20:48:12.467 に答える
3

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

これを修正して foo がポインターを返すようにする 1 つの方法:

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)
于 2008-09-19T20:53:26.150 に答える
1

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

于 2008-09-19T21:00:27.647 に答える
0

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

arr=foo();

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

于 2008-09-19T20:50:26.080 に答える