Что такое хороший шаблон программирования для обработки возвращаемых значений из функций записи файла stdio - PullRequest
8 голосов
/ 20 февраля 2009

Я работаю над кодом, который генерирует много

ignoring return value of ‘size_t fwrite(const void*, size_t, size_t, FILE*)’, declared with attribute warn_unused_result

предупреждения при компиляции с g ++, и я задаюсь вопросом о лучшем шаблоне программирования для фактической записи и обработки возвращаемого значения большого числа отдельных последовательных fwrite с (т. Е. Не одинаковых fwrite в цикле)

Допустим, код выглядит так:

fwrite (&blah, sizeof (blah), 1, fp);
// ... more code ...
fwrite (&foo, sizeof (foo), 1, fp);
// ... more code ...

В настоящее время я думаю о чем-то подобном, но у меня могут возникнуть проблемы с очисткой указателя файла:

if (fwrite (&blah, sizeof (blah), 1, fp) != 1) return someerrorcode;
// ... more code ...
if (fwrite (&foo, sizeof (foo), 1, fp) != 1) return someerrorcode;
// ... more code ...

Я думаю, что этот подход явно лучше, чем вложение, которое слишком быстро сошло бы с ума:

if (fwrite (&blah, sizeof (blah), 1, fp) == 1) {
   // ... more code ...
   if (fwrite (&foo, sizeof (foo), 1, fp) == 1) {;
      // ... more code ...
   }
}

Конечно, уже есть установленный образец наилучшей практики для такого рода вещей, хотя?

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

dummy = fwrite (&blah, sizeof (blah), 1, fp);
// ... more code ...
dummy = fwrite (&foo, sizeof (foo), 1, fp);
// ... more code ...

Обновление: Я удалил тег c ++, поскольку этот код на самом деле просто компилируется с использованием g ++, поэтому необходимы решения на основе c, чтобы соответствовать остальной части кода.

Ответы [ 13 ]

0 голосов
/ 20 февраля 2009

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

int safe_fwrite(FILE *file, const void *data, size_t nbytes, unsigned int retries);
void print_and_exit(const char *message);

Тогда ваш основной код может быть записан как

#define RETRIES 5
if(!safe_fwrite(fp, &blah, sizeof blah, RETRIES))
  print_and_exit("Blah writing failed, aborting");
if(!safe_fwrite(fp, &foo, sizeof foo, RETRIES))
  print_and_exit("Foo writing failed, aborting");
0 голосов
/ 20 февраля 2009

Вложенность плохая, а множественные возвраты тоже не годятся.

Я использовал следующий шаблон:

#define SUCCESS (0)
#define FAIL    (-1)
int ret = SUCCESS;

if (!fwrite(...))
    ret = FAIL;
if (SUCCESS == ret) {
    do_something;
    do_something_more;
    if (!fwrite(...))
        ret = FAIL;
}
if (SUCCESS == ret)
    do_something;

return ret;

Я знаю, что это выглядит некрасиво, но у него одна точка возврата, нет чрезмерного вложения и очень легко поддерживать

0 голосов
/ 20 февраля 2009

Вы можете удалить предупреждения следующим образом:

(void) fwrite ( ,,,, );

Если обратиться к вашему основному вопросу, если какой-либо из вызовов fwrite () завершится неудачно, я думаю, что продолжать его не имеет смысла, так как выходные данные предположительно повреждены. В этом случае, и, как вы пометили этот C ++, я бы выбросил исключение.

...