私は C でポインターと構造体を使用する方法を学んでいます。当然のことながら、言語がどのように機能するかをさらに理解するために、意図的にコードを壊そうとしています。期待どおりに動作するテストコードを次に示します。
#include <stdio.h>
#include <stdlib.h>
struct pair {
int x;
int y;
};
typedef struct pair pair;
void p_struct( pair ); //prototype
int main( int argc, char** argv ) {
pair *s_pair;
int size, i;
printf( "Enter the number of pair to make: " );
scanf( "%d", &size );
getchar();
printf( "\n" );
s_pair = (pair*)malloc( size * sizeof(pair) );
for( i = 0; i < size; i++ ) {
s_pair[i].x = i;
s_pair[i].y = i;
p_struct( s_pair[i] );
}
getchar();
return (EXIT_SUCCESS);
}
void p_struct( pair s_pair ) {
printf( "\n%d %d\n", s_pair.x, s_pair.y );
}
前に述べたように、このコードは私が知る限り機能しています。
次に、コードの一部を次のように変更することにしました。
for( i = 0; i < size + 3; i++ ) {
s_pair[i].x = i;
s_pair[i].y = i;
p_struct( s_pair[i] );
}
この変更により、期待したセグ フォールト エラーは発生しませんでした。scanf 関数を使用して変数サイズに値を割り当てるときに明示的に設定したバッファーを超えたにもかかわらず、すべての「ペア」が出力されました。
ポインターを理解しているので (間違っている場合は訂正してください)、サイズsize*sizeof(pair)のメモリの連続ブロックは、ペアs_pair型のポインターに対して malloc 関数を呼び出したときに、ヒープ内のメモリ マネージャーによって予約されます。私がしたことは、 for ループを条件i < size + 3に変更したときに、メモリの最後に割り当てられたアドレスを超えたことです。
これを正しく理解していれば、ポインターが予約済みのメモリ制限を超えて、その右側に隣接するものが他のデータによって占有されていないために、たまたまクリアになったのでしょうか? バッファをオーバーフローさせたときのこれは正常な動作ですか?
さらに、 i < size + 15の for ループ条件でテストしたときに、セグ フォールトを受け取りました。問題は、それでも出力を印刷することです。のように、私が作成したp_struct関数に従って、サイズ= 10の場合、ペア「0 0」からペア「24 24」を出力します。プログラムは、最後にある getchar() の 1 つに到達した後でのみ、seg fault によってクラッシュします。私のプログラムは、バッファを超えるペアに値を割り当て、それらを画面に出力し、getchar() に到達したときに突然セグメント障害でクラッシュすることを決定できますか? i < size + 3に問題はないようです(まだ間違っていますが)。
念のため、通常のポインター配列を使用してこの動作もテストしました。
int size, i, *ptr;
scanf( "%d", &size );
ptr = (int*)malloc( size * sizeof(int) );
for( i = 0; i < size + 15; i++ )
ptr[i] = i;
これにより、上記とまったく同じ結果が得られます。i < サイズ + 3では、セグ フォールトの問題はないようです。
最後に、配列でもテストしました。
int i, array[10];
for( i = 0; i < 25; i++ )
array[i] = i;
i < 25の条件では、必ず seg fault が発生します。i < 15に変更すると、seg fault は発生しません。
私の記憶が正しければ、ポインターの配列と配列の唯一の違いは、配列に割り当てられたメモリがヒープではなくスタックにあることです (これについてはよくわかりません)。それを念頭に置いて、array[10]がセグ フォールトを生成しない場合にi < 15という事実を考慮すると、なぜi < 25が問題になるのでしょうか? その for ループの間、配列はスタックの一番上にありませんか? 余分な 60 バイトを気にしないのに、なぜ余分な 100 バイトを気にするのでしょうか? その配列バッファの上限が、スタック全体用に予約されているメモリの任意のチャンクの最後までないのはなぜですか?
うまくいけば、これらすべてが、少し酔っ払った男のとりとめのないものを読むことを決心した人にとって意味のあるものになることを願っています.