free() 是否设置了 errno?

Does free() set errno?

如果 bufmalloc() 分配的字符缓冲区,free(buf) set/reset errno?

假设我想将缓冲区写入文件,然后释放它,因为我不再需要它了。

假设代码的错误策略是 return -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。

linux man page for free() 也是 malloc() 等的手册页。它提到了 malloc() 设置 errno,但没有提到 free()

GNU C Library manual page for freeing dynamic memory没有提到free()是否设置了errno。

所以我写了一个简短的程序来强制写入错误,这样我就可以看到 free() 是否重置了 errno,但它没有。我想知道我是否应该依赖这个结果以及 free() 如此重要以至于 "of course it doesn't set 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 to set errno (although POSIX doesn't currently forbid it, so an implementation might do so - refer to 以获得更多详细信息)。但这与您的担忧无关。

您检查错误的方式不正确。您应该检查 fputs 的 return 值,并检查它是否小于 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;

如果引用没有说明函数 return 在失败时 errno 中的错误代码,它不会。

errno 设置为错误代码的函数(几乎)总是以另一种方式表示 errno 包含当前错误代码 - 内存分配函数 return NULL, 许多其他函数 return 零或负数,等等。
此类函数如果成功则不需要以任何方式修改 errno,而且通常不会。

您通常无法通过检查 errno 来确定是否出了问题;它仅用于在您知道出现错误后检索更多信息。

最终规则的一个例外是 strto{l, d, ul} 系列,但第一段也适用于这些系列。
而且它们也不一定设置 errno 除非它们失败,因此您需要先清除它,否则它可能包含陈旧的错误代码。

C标准中对free的描述中没有提到errno。所以你可能不依赖这个功能。

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

3...The value of errno may be set to nonzero by a library function call whether or not there is an error, provided the use of errno is not documented in the description of the function in this International Standard.

并且errno的使用没有记录在C标准中free的描述中,正如我上面已经说过的那样。

符合 POSIX 的 free 可能会设置 errno 今天 但这将在未来变得更好。详情:

  1. The Open Group Base Specifications Issue 7 definition of errno 声明如下:

No function in this volume of POSIX.1-2008 shall set errno to 0. The setting of errno after a successful call to a function is unspecified unless the description of that function specifies that errno shall not be modified.

  1. free 的定义本身并没有指定 freeerrno 的作用。

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

但是,规范的第 8 期(正在进行中)将 require free to specifically guarantee that it will not set errno 通过有效输入。

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

您可以使用 RAII 释放 malloced 内存,并检查 fputs 的 return 值。那将是宽限码。

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

是的,free() 可能会破坏各种系统上的 errno。 gnulib 通过替换此类平台上的 free() 来避免此问题,目前它记录为: “glibc 2.32,Mac OS X,FreeBSD,NetBSD,OpenBSD 4.4,Minix,AIX,HP-UX,IRIX,Cygwin,mingw,MSVC”