-1

非常にばかげた質問のように見えます: 配列ポインターを宣言する方法は次のとおりです。

double * y = new double[26];

この宣言の後、プログラムの実行中に y を監視したところ、次のような結果が得られました。

name    value
y[224] 8.691694942331e-310#DEN
y[225] CXX0030: Error: Expression cannot be evaluated

では、26 の長さで宣言された double 配列に 224 の要素があるのはなぜでしょうか? ありがとう。

編集:しかし、私はこのコードを試しましたが、うまくいきました!

int nPt = 26;
double * y = new double[nPt];
y[224] = 0;

y[224] がない場合、その値がどのように割り当てられる可能性がありますか?

4

4 に答える 4

5

を使用してメモリを割り当てるnew double[26]と、システムは、少なくとも26 x sizeof(double)のスペースを持つメモリのチャンクをアプリケーションに提供します。割り当て関数は、実際に、メモリ割り当てのメタデータ内のどこかに番号26(または他の方法で番号26を取り戻すことを可能にするもの)を格納します。

ただし、デバッガーは要素の数が26であることを「把握」することはできず、これがいくつかのdouble値へのポインターであることを単に認識しています。26を超えているように見えるように要求すると、「未定義動作」の土地にいることになります。何かが発生する可能性があり、発生する可能性もあります。「期待」どおりに完全に表示されることを含めます(つまり、メモリは読み取り可能で、「double」として表示できる値が含まれています。次に、要素224に到達すると、デバッガーはメモリを読み取ることができません。より長く(OSが「使用不可」とマークしたため)停止します。50000000であった可能性があります[この場合、ここに到達してこの質問をするまでにさらに数時間かかる可能性があります...]

右。簡単にするために、100KBのRAMを搭載したコンピューターがあるとします。プロセッサがどのメモリをどの目的に使用するかを割り当てる方法は、一度に4KBのページになります。つまり、25ページあります。それらのページのいくつかはあなたの「ヒープ」です(newそのメモリを取得します)。1つのメモリ割り当ては、このような4KBページの一部を取得します。私たちの記憶がたまたまページ番号18-18*4096 = 73728から77823にあるとしましょう。ページ19は、「未使用」としてマークされています。このページ内の割り当ては168バイトです(最初の168バイトは他の何かに使用されます)-したがって、アドレスは73896です。現在、26 * 8 = 208バイトなので、「次に使用可能なバイト」は73728 + 376=74104です。ページ。したがって、y [0]のアドレスは73896であり、各doubleは8バイトを使用します。74104(インデックス26、割り当てられたメモリの外にあるもの)に到達しても、まだ18ページにあり、プロセッサ/OSによると「使用可能」です。プロセッサが「そこに行けない」と言う前に、77824までずっと行かなければなりません。74104-77824 = 3720バイト、または465 * sizeof(double)。しかし、使用しないように言われたメモリを使用しています。それで、

これがそれをかなりうまく説明することを願っています。

4KBである理由は、プロセッサがメモリのすべての1バイトを追跡する必要がある場合、そのバイトが使用可能かどうかを追跡するにはメモリが多すぎるためです。4KBは、「十分な時間外に出たときに検出する」と「容量を使いすぎる」の間の適切な妥協点です。

于 2013-03-13T19:21:58.037 に答える
5

配列には 26 個の要素しかなく、その範囲を超えています。それは未定義の動作です。プログラムがクラッシュする必要はありません。何かが起こる可能性があるというだけです。これは悪いことであり、避ける必要があります。

于 2013-03-13T19:13:31.580 に答える
4

では、26 の長さで宣言された double 配列に 224 の要素があるのはなぜでしょうか?

そうではありません。デバッガーは、y要素が 26 個しかないことを認識できないようです。

しかし、私はこのコードを試してみました。

int nPt = 26;
double * y = new double[nPt];
y[224] = 0;

コードには未定義の動作があります。これは、クラッシュする必要があるという意味ではありません。好きな方法で失敗する(またはしない)のは自由です。

于 2013-03-13T19:13:52.597 に答える
0

配列は C/C++ には存在しません。実際、t[i] のような式は、アドレス t の先にある i 番目のメモリ位置にアクセスしたいということを示す簡単な方法 (構文糖衣) にすぎません。new とサイズ N (new int[N]) のメモリ チャンクを割り当てると、返されたアドレスから N メモリ ロケーションに安全にアクセスできるアドレスがシステムから提供されます (N メモリ ロケーションと言ったときは、は N バイトではなく、N*sizeof_one_element_in_bytes です)。しかし、C/C++ では、返されたアドレスから派生した任意のアドレスを計算できます。不正なアドレスにアクセスしないようにするのはユーザー次第です。C/C++ ランタイムは配列のサイズについて何も認識していないため、この種のエラーからユーザーを保護することはできません。C/C++ ポインターは非常にエラーが発生しやすいため、慎重に使用する必要があります。これは、機械に近づけたり、効率的にしたりするために支払う代償です。

于 2013-03-13T22:32:02.123 に答える