はい、プログラムにメモリ リークがあります。
int *in, *begin;
in = (int *)malloc(sizeof(int)); /* allocate space for 1 int, at location "X" */
begin = in;
while ((x = getchar()) != EOF) {
*in = x;
in++; /* "in" increments address (to location) "X+1" */
in = (int *)malloc(sizeof(int)); /* address "X+1" is lost as malloc returns
a different memory location, *not*
necessarily at "X+2". Access to
previous data other than pointed to by
"begin" is lost */
}
*in = '\0'; /* this makes probably more senese than assigining EOF here */
free()
メモリを割り当てるときに、対応する呼び出しが必要です。
また、入力が正しく保存されているとは思いません。
in
データを格納するためのメモリの連続ブロックが与えられることはありません。代わりに、 an を格納するサイズの単一のメモリ ロケーションが繰り返し割り当てられ、 に割り当てられますが、このメモリがどこにあるかは実際にはわからないため、単一のポインタだけがそれらを追跡しているため、これらの割り当てはすべて失われます。int
in
in
つまり、リークは、 のサイズのメモリを繰り返し割り当て、int
に割り当てin
、次にループによってその場所への参照を失うことで構成されます。
変数begin
は最初に入力された最初の項目を指しますが、出力ループでポインター値が 1 ずつインクリメントされるため、その後不明なメモリをトラップします。
より良いアプローチは、開始時に単一のより大きな連続バッファーを割り当ててから、in
ポインターをインクリメントするときにそれを使用するか、より少ない量で開始し、realloc()
必要に応じてメモリ使用量などを監視することです (ただし、節約するためのオーバーヘッドははるかに大きくなります)。数バイトのメモリ)。
EOF
また、に割り当てるのではなく、最初のループの最後にin
、null 文字を入れる方が理にかなっています。
最後に、free(in)
プログラムの最後の呼び出しは、1 つのメモリ ロケーションのみを解放し、以前に割り当てられた他のメモリは解放しません。
これは機能する簡単にまとめられたバージョンです。元のコードに最小限の変更を加え、コード構造をそのまま維持しようとしました(そもそも2つのループでこのように書く理由があったと思います) 1 つのループだけで、はるかにコンパクトに記述できます。
最初に100文字のスペースを割り当て、必要に応じてこれを調整するか、最初は割り当てを少なくしてから、必要に応じてメモリ消費量とrealloc()
メモリを増やします(これは最初の意図だったと思いますが、正しく実装されていません)。
int main(void) {
int x;
int *in, *begin;
int *start_loc;
in = (int *)malloc(sizeof(int) * 100); /* continious space */
begin = in;
start_loc = in; /* keep track of start location for final free() call */
while ((x = getchar()) != EOF) {
*in = x;
in++;
}
*in = 0; /* terminator for the input string/data */
while (*begin != 0) { /* simplified */
putchar(*begin);
begin++;
}
free(start_loc); /* free allocated memory */
return 0;
}
これは、新しい変数を使用せずにstart_loc
(たとえば、再利用in
して) 記述できますが、メモリ割り当ての開始を追跡することの重要性と、割り当てられたメモリを正しく解放する機能を強調するために、この方法で記述することを選択しました。メモリ リークの問題に対処します。