Прочитать содержимое файла неизвестного размера

#c #stdio

#c #stdio

Вопрос:

Я хочу обработать содержимое конфигурационного файла. Файл конфигурации может быть любого размера. Я получаю сообщение об ошибке шины после зависания программы, когда я запускаю следующий код:

 FILE *fp;
struct stat st;
char *buffer;

fp = fopen(CONFIG_FILE, "r");
if (fp == NULL) {
    // error handling and cleanup omitted for brevity
}

fstat(fileno(fp), amp;st);
fread(buffer, sizeof(char), st.st_size, fp);
fprintf(stderr, "%sn", *buffer);
fclose(fp);
  

Я прочитал, что ошибка шины может быть вызвана переполнением буфера. Я почти уверен, что у меня происходит переполнение буфера с моим char *buffer . Но тогда, как я могу указать размер буфера во время выполнения?

РЕДАКТИРОВАТЬ — Ошибка шины была вызвана моей ленью жесткого кодирования 1 в вызове fread. Пример кода был обновлен, чтобы исправить это, используя sizeof(char) вместо этого.

Комментарии:

1. sizeof(char) == 1 гарантировано.

2. @Alok, это то, что я думал, но произошел сбой, когда у меня был 1… ну что ж, жесткое кодирование в любом случае плохое

3. Стандарт C гарантирует, что sizeof(char) равно 1. Так что в этом случае с жестким кодированием все в порядке.

Ответ №1:

Использовать malloc(3) . Поместить:

 buffer = malloc(st.st_size);
  

Перед вашим вызовом в fread() . Не забудьте освободить buffer , когда закончите с этим!

Вы, вероятно, также не хотите использовать его *buffer в своем printf() вызове. Если вы собираетесь попытаться распечатать весь файл таким образом, вам нужно обязательно выделить дополнительный байт для завершения строки нулем.

Комментарии:

1. @Карл, когда я вводю malloc(st.st_size 1), я явно задаю последнему элементу значение ?

2. @Mad Rapper X — это должно сработать, да. @muntoo, о чем ты спрашиваешь?

Ответ №2:

Вы можете выделить память с помощью malloc :

 buffer = malloc(number_of_bytes_to_allocate);
if(buffer == NULL) {
    // error allocating memory
}
  

free когда вы закончите с этим!

 free(buffer);
  

Ответ №3:

В C99 и при условии, что ваш конфигурационный файл не должен находиться в диапазоне MiB или большем, вы могли бы использовать VLA:

 FILE *fp = fopen(CONFIG_FILE, "r");
if (fp == NULL) {
    // error handling and cleanup omitted for brevity
}

struct stat st;
fstat(fileno(fp), amp;st);  // Error check omitted
char buffer[st.st_size 1];
fread(buffer, sizeof(char), st.st_size, fp);
buffer[st.st_size] = '';
fprintf(stderr, "%sn", *buffer);
fclose(fp);
  

Комментарии:

1. Осторожно.. кто-то может случайно или злонамеренно передать вам двоичный файл. Так что же такое ‘%s’. Никогда не предполагайте, что входные данные соответствуют вашим ожиданиям!