【问题标题】:perror and strerror with close(2) involved涉及 close(2) 的 perror 和 strerror
【发布时间】:2020-09-14 21:14:57
【问题描述】:

我已经实现了这个带有 close(2) 的代码,你们中的许多人(包括我自己)都知道这会关闭标准错误,但是关闭它的主要影响是什么?

为什么要打印“main: Success”?不应该每个目录都有“。”可以打开的目录吗?

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>


int main() {
    close(2);
    if (fopen(".","r")) 
    {
        printf("main: %s \n", strerror(errno));
    }
    return 0;
}

另一方面

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

int main() {
    close(2);
    if (fopen(".","r")) 
    {
        perror("main");
    }  
    return 0;
}

这不打印任何东西,有什么想法吗?

【问题讨论】:

  • 我的猜测是对fopen 的两次调用都成功了,但是由于您已关闭stderr,因此您无法在第二个sn-p 中看到该消息(perror 使用stderr) ,在第一个 sn-p 中尝试 fprintf(stderr, "main: %s \n", strerror(errno)); 看看会发生什么。
  • @DavidRanieri 如果 stderr 已关闭,则无法打印到 stderr。
  • @Barmar 再也不奇怪了 :) 是的,这就是重点

标签: c system-calls errno unistd.h strerror


【解决方案1】:

标准错误是应该打印错误消息的地方。所以perror() 在标准错误上打印它的错误信息。如果您关闭标准错误,则无法打印该消息。

为什么会打印“main: Success”?不应该每个目录都有“。”可以打开的目录吗?

是的,确实如此。你在调用fopen()时没有收到错误,所以errno == 0,这个消息是Success

如果你想在fopen()失败时打印错误信息,你需要测试NULL

if (fopen(".") == NULL) {
    printf("main: %s \n", strerror(errno));
}

请注意,打开文件时,使用的 FD 是最低可用 FD。由于您已关闭 FD 2,因此很可能在打开 . 时使用它。因此,标准错误现在指向您无法写入的. 目录,而perror() 在尝试在那里写入时会出错。但是它不能报告这个错误(它会在哪里报告它?)。

【讨论】:

    【解决方案2】:

    关闭它的主要影响是什么?

    未定义的行为。 C 标准说“在以下情况下行为未定义:[...] 在关联文件关闭后使用指向 FILE 对象的指针的值”,并且POSIX says“stderr 流预计为开放阅读和写作。”

    【讨论】:

      猜你喜欢
      • 2023-03-03
      • 2019-08-12
      • 1970-01-01
      • 2021-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-26
      • 1970-01-01
      相关资源
      最近更新 更多