次のコードがあります。関数は、渡されたget_unlimited_input
場合NULL
は新しい文字列を割り当てます。それ以外の場合は、既存の文字列に文字を追加するだけです。最終的には、余分なバイトを切り捨てます。(多くの再割り当てのテストケースDEFAULT_BUFFER_SIZE
に設定され5
ました)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define DEFAULT_BUFFER_SIZE 5
char *get_unlimited_input(char *buffer) {
size_t current_size;
if (buffer == NULL) {
buffer = malloc(DEFAULT_BUFFER_SIZE * sizeof(char));
current_size = DEFAULT_BUFFER_SIZE;
} else {
current_size = strlen(buffer) + DEFAULT_BUFFER_SIZE;
}
char *cursor = buffer + current_size - DEFAULT_BUFFER_SIZE;
for (;;) {
int current = getchar();
*cursor = (char)current;
cursor++;
if (current == '\n' || current == EOF)
break;
if (cursor >= buffer + current_size) {
current_size += DEFAULT_BUFFER_SIZE;
buffer = realloc(buffer, current_size);
cursor = buffer + current_size - DEFAULT_BUFFER_SIZE;
}
}
*cursor = '\0';
buffer = realloc(buffer, cursor - buffer);
return buffer;
}
int main() {
printf(">");
char *buffer = get_unlimited_input(NULL);
printf(">");
get_unlimited_input(buffer);
}
ほとんどの場合、問題なく動作しますが、最初に117文字を渡し、次に12文字を渡すと、クラッシュします。
>.....................................................................................................................
>............
realloc(): invalid next size
Aborted (core dumped)
python3 -c "print('.'*117+'\n'+'.'*12)" | ./_buffer
realloc(): invalid next size
Aborted (core dumped)
何が問題ですか?
コードには複数の問題があり、診断が示すようにヒープが破損します。
現在割り当てられているサイズに関するあなたの仮定は正しくcurrent_size = strlen(buffer) + DEFAULT_BUFFER_SIZE;
ありません:楽観的すぎます。バッファをcursor - buffer
返す前にバイトに再割り当てするため、文字列の最後にスラックはありません。
あなたはをテスト'\n'
し、EOF
配列にバイトを格納した後。これは改行の意図された動作である可能性がありますがEOF
、文字ではない、については正しくありません。
buffer
withの再割り当てbuffer = realloc(buffer, cursor - buffer);
も正しくありませんcursor
。nullターミネータを指しているため、のサイズを使用してcursor + 1 - buffer
、割り当てられたブロック内にnullターミネータを保持する必要があります。
変更されたバージョンは次のとおりです。
#include <stdio.h>
#include <stdlib.h>
#define DEFAULT_BUFFER_SIZE 16 /* use address alignment as incremental size */
char *get_unlimited_input(char *buffer) {
size_t current_size, pos;
char *p;
if (buffer == NULL) {
pos = 0;
current_size = DEFAULT_BUFFER_SIZE;
buffer = malloc(DEFAULT_BUFFER_SIZE);
if (buffer == NULL)
return NULL;
} else {
pos = strlen(buffer);
current_size = pos + 1;
}
for (;;) {
int c = getchar();
if (c == EOF || c == '\0')
break;
if (pos + 1 == current_size) {
// reallocate the buffer
current_size += DEFAULT_BUFFER_SIZE;
p = realloc(buffer, current_size);
if (p == NULL)
break;
buffer = p;
}
buffer[pos++] = (char)c;
if (c == '\n')
break;
}
buffer[pos] = '\0';
p = realloc(buffer, pos + 1);
return (p != NULL) ? p : buffer;
}
int main() {
printf("> ");
char *buffer = get_unlimited_input(NULL);
printf("got: %s\n", buffer);
printf("> ");
get_unlimited_input(buffer);
printf("got: %s\n", buffer);
return 0;
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加