如果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。
linux man page for free()也是malloc()
等的手册页。它提到malloc()
设置errno,但不是free()
。
GNU C Library manual page for freeing dynamic memory没有提及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));
}
答案 0 :(得分:48)
POSIX没有定义free
来设置errno
(尽管POSIX目前不禁止它,因此实现可能会这样做 - 有关更多详细信息,请参阅@ArjunShankar's answer)。但这与你的担忧并不相关。
您检查错误的方式不正确。您应该检查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;
答案 1 :(得分:34)
符合POSIX标准的free
今天可能设置errno
,但将来会有所改善。详细说明:
errno
定义如下:此POSIX.1-2008卷中的任何功能都不应将errno设置为0.除非该函数的描述指定不应修改errno,否则未指定成功调用函数后的errno设置。
free
本身的定义未指定free
对errno
的作用。这意味着符合free
的实现永远不会将errno
重置为0.但它可能会也可能不会将其设置为非零值。
但是,当传递有效输入时,规范的问题8(正在进行的工作)将require free
to specifically guarantee that it will not set errno
。
glibc已经准备好遵守这一新要求。
答案 2 :(得分:16)
C标准中对errno
的描述中没有任何关于free
的说法。所以你可能不会依赖这个功能。
根据C标准(7.5错误<errno.h>
)
3 ...如果使用errno,则可以通过库函数调用将errno的值设置为非零,无论是否存在错误 没有在此功能的描述中记录 国际标准。
正如我上面已经说过的那样,{C}标准中errno
的描述中未记录free
的使用。
答案 3 :(得分:13)
如果引用没有说明函数在errno
失败时返回错误代码,则不会。
将errno
设置为错误代码(几乎)的函数始终以errno
包含当前错误代码的另一种方式发出信号 - 内存分配函数返回NULL
,许多其他函数返回零或负数,依此类推。
如果成功,则不需要以任何方式修改errno
这些函数,通常不会。{/ p>
您通常无法检查errno
以确定是否出现问题;它仅用于在您知道出现错误后检索更多信息。
最终规则的一个例外是strto{l, d, ul}
系列,但第一段也是如此。
它们也不一定设置errno
,除非它们失败,所以你需要先清除它,否则它可能包含陈旧的错误代码。
答案 4 :(得分:-2)
您可以使用RAII释放malloced内存,并检查fput的返回值。这将是恩典代码。
//if malloc successfully
AutoFree af(buf);
if (fputs(buf, somefile)) {
LOG("something err:%s", strerror(errno));
}
return 0;