2

同じプログラムの例が 2 つあります。このプログラムには、配列を作成し、配列へのポインターを返す関数があります。

最初のプログラム (C):

#include <stdio.h>
#include <stdlib.h>

#define N 5

int* GetValues()
{
   int items[N] = { 1, 2, 3, 4, 5 };
   return items;
}

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

    int *array = GetValues();    
    int i;    
    for(i = 0; i < N; i++)
    {
        printf("%d\n", array[i]);
    }    

    return (EXIT_SUCCESS);
}

2 番目のプログラム (Java):

package tests;

public class Tests {

    public static int[] foo() {        
        int array[] = { 1, 2, 3, 4, 5 };
        return array;        
    }

    public static void main(String[] args) {        
        int[] array = foo();        
        for(int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }                
    }
}

Java プログラムの結果は次のとおりです。1、2、3、4、5

C プログラムの結果は次のとおりです。 1 -1075386156 -1218492432 1 -1216747208

なぜこれほど異なる結果が得られるのでしょうか。私のバージョンは次のとおりです。

GetValues() 関数内の C プログラムでは、items[] ローカル配列が作成され、初期化されます。return命令は配列の先頭へのポインタを返しますが、この配列はその関数のローカルメモリに割り当てられます。GetValues() 関数の最後の命令が呼び出されると、ローカル メモリが破棄されます。この場合、そこに格納されているデータを予測することはできず、命令を出力するものもわかりprintf("%d\n", array[i])ません (メモリが破壊され、値も破壊されているのも不思議ではありません)。

Java プログラムでは、次の状況があります。JAVA の配列はオブジェクトです。Java のオブジェクトはヒープに格納されています。したがって、foo()メソッドを実行した後、オブジェクトarrayが作成され、ヒープに配置されます。メソッドを実行した後、ローカル変数はarray消去されますが、 -object へのポインターはヒープ内に残っています (ガベージ コレクターは、このオブジェクトをいつ削除する必要があるかを理解します)。これが、正常に出力できる理由です。

私は正しいですか?この機能を正しく理解していますか? そうでない場合、誰かが私を修正できますか? 前もって感謝します。

PS私の英語で申し訳ありませんが、私の問題を多かれ少なかれ明確に説明したいと思います。

4

4 に答える 4

2

Cプログラムでint* GetValues()は、未定義の動作であるローカル変数へのポインターをitems返しています。関数から戻ると存在しません。これは、コードを修正する 1 つの方法です。

int *items = malloc( sizeof(int) * 5 ) ;
items[0] = 1 ;
// initialize rest of array 
return items;

free必要なものを覚えておいてくださいmalloc

Java では配列はオブジェクトであり、オブジェクトは参照を介して渡されるため、Java ではオブジェクトへの参照がなくなるとオブジェクトをガベージ コレクションするため、同じ問題は Java には存在しません。

于 2013-05-30T19:06:20.177 に答える
1

Java配列はオブジェクトです(Java言語仕様からの引用):

オブジェクトは、クラス インスタンスまたは配列です。

そのため、アプリケーションの Java バージョンでは、fooメソッドで作成された配列は実際にはスタックではなくヒープに格納されます。fooしたがって、メソッドの外からアクセスできます。

于 2013-05-30T19:05:55.583 に答える