【问题标题】:Why does do stdio.h prints write to file opened with file descriptor?为什么 stdio.h 打印写入使用文件描述符打开的文件?
【发布时间】:2012-03-06 22:26:50
【问题描述】:

我只想写入文件描述符的是输入字符串。但是,它也会写入 fprintf 中传递的错误消息。有人可以解释为什么它会这样吗?这个小程序显示了行为。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main(void)
{
    int fd;
    mode_t mode = S_IRUSR | S_IWUSR;
    char *filename = "file.txt";
    char *input = "hello world";
    char output[20];

    // create and close
    if((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, mode)) == -1)
    {
        fprintf(stderr, "Error.\n");
        return -1;
    }
    close(fd);

    // just open
    if((fd = open(filename, O_RDWR, mode)) == -1)
    {
        fprintf(stderr, "Error.\n");
        return -1;
    }

    if(write(fd, input, 200) == -1)
    {
        fprintf(stderr, "Error.\n");
        return -1;
    }

    // move back to beginning
    if(lseek(fd, 0, SEEK_SET) == -1)
    { 
        return -1;
    }

    if(read(fd, &output, 200) == -1)
    {
        fprintf(stderr, "Error.\n");
        return -1;
    }

    printf("%s\n", output);

    return 0;
}

【问题讨论】:

  • 您没有向我们展示足够多的程序来回答您的问题。请提供一个完整的例子。
  • “即使达到了”是什么意思?我似乎明白了文件的输出似乎正在发生的要点,即使您的诊断正在打印。我怀疑你认为正在发生的事情并没有真正发生,你只是在某种程度上让自己感到困惑。请注意,您的 open() 调用不会截断文件。您是否正在检查 open() 是否成功?也许您并没有真正打开文件,而文件描述符实际上很糟糕。但是当您查看文件时,您正在查看正确的文件并且数据就在那里。执行 ls -l 时文件上的时间戳是多少?
  • 我只想写入文件描述符的是块中的内容。但是,当我在写入文件后打开文件时,它包含块中的消息和所有 fprintf 消息,例如无法写入。\n
  • 你能发布一个小的可编译程序来重现这个吗?
  • 我添加了一个显示行为的程序。

标签: c file unix stdio file-descriptor


【解决方案1】:
write(fd, input, 200)

//...

read(fd, &output, 200)

您正在写入和读取包含有效数据的数组 - inputoutput 都不接近 200 字节。那么谁知道文件中最终会发生什么(我不确定为什么read() 不会使您的程序崩溃)?

【讨论】:

    【解决方案2】:

    我敢打赌,'fd' 的声明或范围很奇怪。 UNIX 中的文件描述符只是一个介于 0 和某个最大值(以前是 20,现在更大)之间的整数,它是表的索引。 STDIN==0STDOUT==1STDERR==2

    如果你看到你描述的行为,不知何故 fd == 2。

    【讨论】:

    • fd 应该如何声明。目前,它已被声明但在调用 open 之前未设置。然后,如果它== -1,我出错,否则返回3。
    【解决方案3】:

    这听起来像你closed stderr 或什么的。不知何故,fdstderr 包含相同的整数,因此您的write(肯定失败)和fprintf 都使用相同的文件描述符。尝试检查errno 的值,也许使用perror 或其他东西,看看那里是否有更多信息。

    归根结底,您应该在调试器下运行它并观察fdstderr 的值。

    【讨论】:

    • 好吧,从 open 返回的 fd 是 3,这是正确的,因为我正在写入另一个文件。不是 2 的 stderr。
    【解决方案4】:

    这听起来不像是 fd 问题……而是内存错误。请注意,您的格式字符串没有被替换,但您得到了实际的格式字符串。你的 write 使用 block 和 read 使用 &amp;block 的事实似乎有点可疑,尽管如果没有任何上下文很难说是不是这样。听起来您正在从程序中写入恰好包含程序字符串的内存。

    我建议使用 valgrind 运行您的程序。

    根据添加的代码更新:

    read()write() 不适用于“字符串”,它们会写入您要求的字节数。您的输入是一个字符串文字,它比 200 字节小得多......因为很可能所有字符串文字都存储在您程序中的同一常规区域中,这就是为什么您会看到其他人在您的输出中弹出。

    还有一些其他问题——您的输出缓冲区不够大,无法处理您请求的read(),您可能希望在写入和读取之间使用lseek(),以便能够读取再次数据。

    【讨论】:

    • 我在原始帖子中添加了一个示例程序。我没有使用相同的变量进行读写,这只是一个例子。对此感到抱歉。
    【解决方案5】:

    输入的长度不是 200 个字符。用 strlen(input) 替换 200

    或者使用这个宏

    #define write1(s) write(1, s, strlen(s))
    

    注意,你需要#include for strlen

    【讨论】:

    • 那就是 。 :)
    猜你喜欢
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 2018-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-31
    相关资源
    最近更新 更多