free()是否设置了errno?

如果buf是一个malloc()分配的字符缓冲区,是否free(buf)设置/重置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。

free()的linux手册页也是malloc()的手册页等。它提到了malloc()设置errno,但不是free()

释放dynamic内存的GNU C库手册页没有提及free()是否设置了errno。

所以我写了一个简短的程序来强制写入错误,所以我可以看到如果free()重置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,"%s\n", "Hello, World!"); FILE *badfile; badfile = fopen("/dev/null","r"); fputs(buf, badfile); free(buf); printf("%d\n", errno); printf("%s\n", strerror(errno)); } 

POSIX没有定义free地设置errno (虽然POSIX目前不禁止它,所以一个实现可能会这样做 – 请参阅@ ArjunShankar的答案了解更多详细信息)。 但是,这与你的担心无关。

您检查错误的方式不正确。 您应该检查fputs的返回值,并检查它是否小于0 。 如果是,那么你可以检查errno来找出导致失败的原因,但是这是可选的(并且在调用任何进一步的function之前应该完成)。

所以,这样的事情应该做的伎俩:

 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. errno的“开放组织基本规范”第7期定义指出:

在本卷的POSIX.1-2008中没有函数将errno设置为0.成功调用函数之后的errno的设置是未指定的,除非该函数的描述指定不应该修改errno。

  1. free的定义本身并没有指定什么freeerrno

这意味着一个兼容的free实现永远不会将errno重置为0.但它可能会或可能不会将其设置为非零值。

然而,规范的第8期(正在进行的工作)将要求free保证在通过有效input时不会设置errno

glibc已经准备好遵守这一新的要求。

在C标准的free描述中没有关于errno的说法。 所以你可能不会依赖这个function。

根据C标准(7.5错误<errno.h>

3 … errno的值可以通过库函数调用设置为非零值,只要在本标准的function描述中没有loggingerrno的使用。

如前所述,在C标准的free描述中没有loggingerrno的使用。

如果引用没有声明一个函数在errno失败时返回一个错误代码,它将不会。

errno为错误代码(几乎)的函数始终以另一种方式指示errno包含当前错误代码 – 内存分配函数返回NULL ,许多其他函数返回零或负数,等等。
如果成功的话,这样的function不需要以任何方式修改errno ,通常也不需要。

你通常不能检查errno以确定是否出了问题; 一旦你知道有错误,它只是用来检索更多的信息。

最后一条规则的一个例外是strto{l, d, ul}系列,但是第一段对于那些家庭来说也是正确的。
而且它们也不一定设置errno除非它们失败,所以你需要先清除它,或者它可能包含一个陈旧的错误代码。

你可以使用RAII来释放malloced内存,并检查fput的返回值。 这将是宽限期的代码。

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