在Linux中,fwrite命令没有设置errno,如何在失败的情况下获得正确的errno

时间:2016-05-20 10:40:21

标签: c linux fwrite

来自linux中的fwrite的手册页,

描述        函数fread()从stream指向的流中读取数据的nmemb元素,每个字符长为大字节,将它们存储在ptr给出的位置。

   The function fwrite() writes nmemb elements of data, each size bytes long, to the stream pointed to by stream, obtaining them from the location given by ptr.

   For nonlocking counterparts, see unlocked_stdio(3).

返回值        成功时,fread()和fwrite()返回读取或写入的项目数。此数字等于仅在size为1时传输的字节数。如果发生错误,或者到达文件末尾,        返回值是短项目计数(或零)。

   fread() does not distinguish between end-of-file and error, and callers must use feof(3) and ferror(3) to determine which occurred.

现在我的问题是: 假设由于驱动器上没有空间而发生fwrite()系统调用失败。我们怎样才能得到它的错误。因为fwrite没有设置errno以防万一。

以防errno为: 头文件定义整数变量errno,其中 由系统调用和一些库函数设置 错误表明出了什么问题。

谈论编程语言: C

3 个答案:

答案 0 :(得分:1)

由于fwrite在发生故障时没有设置errno :不完全正确。 fwrite唯一可能的错误是在调用基础write系统调用期间发生的错误。在这种情况下,将设置errno变量,但write调用将可用,并且您将能够直接使用strerror或perror函数来获取错误的文本描述。

BTW,fwrite 系统调用,但标准库函数:不直接调用内核函数。

答案 1 :(得分:1)

fwrite()不是直接的系统调用,通常所有通过FILE *指针完成的I / O都被缓冲。无法保证在那个时候对fwrite()的调用实际上会执行写操作。错误可以立即返回,也可以稍后通过使用FILE *调用函数来返回。但是,fclose()将写出所有剩余的缓冲数据,如果写操作失败,将返回错误。

总而言之,您需要在每次调用fwrite()fread() fclose()时检查错误。如果您想避免在各处进行错误检查,则可以随时调用ferror()来检查FILE *的错误状态。

在发生错误时设置变量errno,因为C库在内部调用read()write(),并且在发生错误时设置errno

答案 2 :(得分:1)

fwrite()不能因EOF而失败,但是fread()可以。

对于fwrite(),如果它没有写入告诉您的相同数量的项目,则会发现错误,因此您应按以下方式进行检查:

size_t written = fwrite(buf, element_size, num_elements, file);
if (written != num_elements) {
   //error , here errno do get set and you can inspect it/print it etc.
}

现在,FILE *具有内部缓冲区,因此,除非内部缓冲区已满,否则fwrite()调用实际上可能不会将数据写入操作系统或文件。

这意味着您还必须fflush() FILE *,并且在每次fwrite()调用之后也要检查错误,如下所示:

if (fflush(file) == EOF) {
       //error , here errno do get set and you can inspect it/print it etc.
}

或者您必须接受在您以后执行的任何fwrite()调用中都可能给您带来潜在的写入失败,例如这些调用恰好会自动冲洗(*)FILE *。 而且,您在调用fclose()时还必须检查错误:

if (fclose(file) == EOF) {
       //error , here errno do get set and you can inspect it/print it etc.
}

对于fread(),您可以检查errno是否失败。处理完fread()个呼叫的所有数据后,就可以

if (ferror(file)) {
     //error , here errno do get set and you can inspect it/print it etc.
}