C free()是否设置了errno?
如果C free()是否设置了errno?,c,linux,memory-management,C,Linux,Memory Management,如果buf是malloc()分配的字符缓冲区,free(buf)set/reseterrno 假设我想将缓冲区写入一个文件,然后释放它,因为我不再需要它了 假设代码的错误策略是在出现错误时返回-1 这是在不泄漏内存的情况下写出缓冲区和错误检查的正确方法吗 fputs(buf, somefile); free(buf); if (errno) return -1; 还是我需要考虑自由可能设置ErnNO,如… fputs(buf, somefile); if (errno){ free(
buf
是malloc()
分配的字符缓冲区,free(buf)
set/reseterrno
假设我想将缓冲区写入一个文件,然后释放它,因为我不再需要它了
假设代码的错误策略是在出现错误时返回-1
这是在不泄漏内存的情况下写出缓冲区和错误检查的正确方法吗
fputs(buf, somefile);
free(buf);
if (errno) return -1;
还是我需要考虑自由可能设置ErnNO,如…
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);
如果块的使用允许本地存储错误存在于需要重用的不同位置
所有这些似乎都取决于free()是否设置了errno
这也是malloc()
等的手册页。它提到malloc()
设置errno,但不是free()
没有提到free()是否设置errno
因此,我编写了一个简短的程序来强制执行写入错误,这样我就可以查看free()是否重置了errno,但它没有。我想知道我是否应该依赖这个结果以及free()如此重要以至于“当然它不会设置errno”这一事实
#查看free()是否在错误写入时重置errno
#包括
#包括
#包括
#包括
int main(int argc,字符**argv)
{
char*buf=malloc(256);
snprintf(buf,256,“%s\n”,“你好,世界!”);
文件*坏文件;
badfile=fopen(“/dev/null”,“r”);
FPUT(buf、badfile);
免费(buf);
printf(“%d\n”,错误号);
printf(“%s\n”,strerror(errno));
}
POSIX没有定义设置errno
(尽管POSIX目前没有禁止它,所以一个实现可能会这样做-有关更多详细信息,请参阅)。但这与你的担心无关
检查错误的方式是不正确的。您应该检查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;
int result=fputs(buf,somefile);
/*如果结果<0(在自由调用之前),可以选择在此处读取errno*/
免费(buf);
返回(结果<0)-1 : 0;
如果引用没有说明函数在失败时在errno
中返回错误代码,则不会
将errno
设置为错误代码的函数(几乎)总是以另一种方式发出信号,表示errno
包含当前错误代码-内存分配函数返回NULL
,许多其他函数返回零或负数,依此类推。如果这些函数成功,则不需要以任何方式修改
errno
,而且通常不会
您通常无法检查errno
以确定是否出现了问题;它只用于在您知道发生错误后检索更多信息
最后一条规则的一个例外是strto{l,d,ul}系列,但第一段同样适用于这些规则。而且它们也不一定设置
errno
,除非它们失败,所以您需要先清除它,否则它可能包含一个过时的错误代码。在C标准中对free
的描述中没有提到errno
。因此,您可能不依赖此功能
根据C标准(7.5错误
)
3…如果使用了errno,则无论是否存在错误,库函数调用都可以将errno的值设置为非零
本节中的功能描述中未记录
国际标准
正如我前面所说,C标准中的
free
说明中没有记录errno
的使用。符合POSIX标准的free
可能会在今天设置errno
,但将来会变得更好。详情:
free
对errno
的作用free
实现永远不会将errno
重置为0。但它可能会也可能不会将其设置为非零值
但是,当通过有效输入时,规范的第8版(正在进行的工作)将被删除
已准备好遵守此新要求。您可以使用RAII释放malloced内存,并检查FPUT的返回值。这就是格雷斯密码
//if malloc successfully
AutoFree af(buf);
if (fputs(buf, somefile)) {
LOG("something err:%s", strerror(errno));
}
return 0;
A.此外,
errno
的值在调用未显式设置的函数后未定义,其中包括未失败的函数调用。换句话说,除非上一次调用显式失败,否则不要选中errno
。free
的“误用”与尝试两次释放同一指针一样,不必崩溃,它只是未定义。虽然在许多情况下未定义的行为会导致崩溃,但您不需要求助于do{…}while(0)代码>构造,您还可以使用简单的大括号创建块{…}
。在什么情况下,传递有效输入时可能会释放设置errno?@Random832,这取决于实现。也许有些人不碰errno
。查看glibc的bug报告(但要清楚这还不是bug,因为POSIX还没有被修改),我在回答的最后一行链接到,详细了解glibc的free
@Random832实现中会发生什么,想象一个malloc/free实现在可能的情况下尝试收缩堆,使用适用于底层操作系统的系统调用,例如mmap()、sbrk()等。如果这些系统调用失败,errno将
//if malloc successfully
AutoFree af(buf);
if (fputs(buf, somefile)) {
LOG("something err:%s", strerror(errno));
}
return 0;