Устанавливает ли free () errno?



если buf это malloc() выделенный буфер типа char, делает free(buf) set / reset errno?



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



предположим, что политика ошибок для кода должна возвращать -1 при ошибке.



это правильный способ записать буфер и проверить ошибку без утечки памяти?



fputs(buf, somefile);
free(buf);
if (errno) return -1;


или мне нужно рассмотреть возможность свободной установки errno, как в...



fputs(buf, somefile);
if (errno){
free(buf);
return -1;
}
free(buf);


или, о ужас,



do { 
fputs(buf, somefile);
int save_errno = errno;
free(buf);
errno = save_errno;
if (errno) return -1;
} while(0);


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



все это, казалось бы, зависит от того, устанавливает ли free() errno.



The Linux man page бесплатно () также на man-страницах malloc() и т. д. Он упоминает malloc() установка errno, но не free().



The библиотека GNU C ручная страница для освобождения динамической памяти не упоминает ли free () устанавливает errno.



поэтому я написал короткую программу, чтобы заставить ошибку записи, чтобы я мог увидеть, если free() reset errno, и это не так. Мне интересно, должен ли я полагаться на этот результат и тот факт, что free() настолько важен, что "конечно, он не устанавливает errno."



# See if free() resets errno on a bad write
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv)
{
char * buf = malloc(256);
snprintf(buf,256,"%sn", "Hello, World!");

FILE *badfile;

badfile = fopen("/dev/null","r");

fputs(buf, badfile);
free(buf);
printf("%dn", errno);
printf("%sn", strerror(errno));
}
531   5  

5 ответов:

POSIX не определяет free установить errno (хотя POSIX в настоящее время не запрещает это, поэтому реализация может сделать это - см. @ArjunShankar это!--8--> для более подробной информации). Но это не имеет никакого отношения к вашей проблеме.

то, как вы проверяете ошибки, неверно. Вы должны проверить возвращаемое значение fputs, и проверить, если это меньше, чем 0. Если это так, то вы можете увидеть errno чтобы узнать, что вызвало сбой, но это необязательно (и должно быть сделано перед вызовом каких-либо дополнительных функций).

Итак, что-то вроде этого должно сделать трюк :

int result = fputs(buf, somefile);
/* optionally read errno here if result < 0 (before the free call) */
free(buf);
return (result < 0) ? -1 : 0;

POSIX совместимый free может errno но в будущем это изменится к лучшему. Подробности:

  1. The Вопрос 7 Спецификаций Открытой Группы Низкопробный определение errno указано следующее:

нет функции в этом томе POSIX.1-2008 устанавливает errno в 0. Значение errno после успешного вызова функции не определено, если только описание этой функции указывает, что errno не должен быть изменен.

  1. определение free сам не уточняет что free с errno.

что соответствует free реализация никогда не будет сброшен errno к 0. Но он может или не может установить его в ненулевое значение.

однако, выпуск 8 (незавершенное производство) спецификации будут требуются free в частности, гарантировать, что он не будет ставить errno при передаче допустимого ввода.

glibc уже готовится придерживаться этого нового требования.

там ничего не сказано про errno в описании free в стандарте C. Поэтому вы не можете полагаться на эту функцию.

согласно стандарту C (7.5 ошибки <errno.h>)

3...Значение errno может быть установлено в ненулевое с помощью вызова библиотечной функции независимо от наличия ошибки, при условии использования errno не задокументировано в описании функции в этом международный стандарт.

и использование errno не задокументировано в описании free в стандарте C как я уже сказал выше.

если ссылка не говорят, что функция возвращает код ошибки в errno на провал, это не будет.

функции, которые выделяют errno коду ошибки (почти) всегда сигнализируют по-другому, что errno содержит текущий код ошибки - функции выделения памяти возвращают NULL многие другие функции возвращают ноль или отрицательное число, и так далее.
Такие функции не требуется изменять errno в любом случае, если они преуспеют, и обычно не надо.

вы обычно не можете проверить errno чтобы определить, что-то пошло не так; он предназначен только для получения дополнительной информации, как только вы знаете, что произошла ошибка.

одним исключением из последнего правила является strto{l, d, ul} семья, но первый абзац верен и для них.
И они не обязательно errno за исключением случаев, когда они терпят неудачу, поэтому вам нужно сначала очистить его, или он может содержать устаревший код ошибки.

вы можете использовать RAII для освобождения памяти malloced и проверить возвращаемое значение fputs. Это будет код благодати.

//if malloc successfully
AutoFree af(buf);
if (fputs(buf, somefile)) {
LOG("something err:%s", strerror(errno));
}
return 0;

Comments

    Ничего не найдено.