使用open和fdopen打开文件后程序挂起

4
我正在使用O_RDWR打开文件并提供描述符,然后使用带有"r+"fdopen()中的描述符。我首先使用access()检查文件是否存在,然后检查open()返回-1,然后检查从fdopen()设置的FILE *fp不为NULL

现在,每当我使用fp的任何函数,如fgets()fgetc(),程序就会在终端中挂起。我没有收到编译器警告。有什么想法吗?

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

int main(int argc, char **argv) {
    char buffer[512];
    int file_descriptor;
    FILE *file;

    if (argc != 2) {
        puts("ERROR: Missing argument");
        exit(0);
    }
    else if (access(argv[1], F_OK) == -1) { // Check if file exists
        puts("ERROR: File does not exist");
        exit(0);
    } else if (file_descriptor = open(argv[1], O_RDWR) == -1) { // Check for open() failure
        puts("ERROR: Unable to open file using open()");
        exit(0);
    }

    file = fdopen(file_descriptor, "r+"); // Use descriptor

    if (file == NULL) {
        puts("ERROR: Unable to open file using fdopen()");
        fclose(file);
        exit(0);
    }

    // fscanf(file, "%c", stdout); // Hangs
    // fgets(buffer, sizeof(buffer), file); // Hangs
    printf("%c", fgetc(file)); // Hangs

    fclose(file);

    return 0;
}

你可以使用 fopen 代替 open + fdopen。同时,clang 给出了一堆警告,指出你正在使用 open 的方式不正确。 - Schwern
@Schwern 学校作业要求。由于我搞错了运算符优先级,所以还没有深入研究它! - Insane
另外,你没有开启警告,需要使用cc -Wall命令来开启。如果你的教授没有告诉你这个,那他们真是太不负责任了。我建议你使用C99标准的-std=c99选项,并避免过度依赖GNU扩展。最后,我的建议是现在就学习valgrind - Schwern
@Insane,你可以想象,在这个网站上有数百个重复的问题,但每个问题都有各种用途和不同的标题,很难通过搜索找到这些重复的问题,就像你可能已经发现的那样。 - WhozCraig
2个回答

13

表达式

file_descriptor = open(argv[1], O_RDWR) == -1

如果运行结果与您的期望不符,那是因为等于运算符==比赋值运算符具有更高的优先级。这意味着该表达式更像是

file_descriptor = (open(argv[1], O_RDWR) == -1)

这意味着你的file_descriptor将会是01,具体取决于比较结果。

在赋值时需要使用括号:

(file_descriptor = open(argv[1], O_RDWR)) == -1

因此最好将打开和检查分别放在两行。 - Schwern
@Schwern 这就是我试图变得花哨的结果。 - Insane
@Insane 始终使用括号。 - user6754053

6
除了其他答案之外,我想补充一点。它“挂起”的原因是由于该漏洞实际上导致其读取标准输入(文件描述符0)。尝试输入一些内容,它就会读取它。

这也是非常好知道的。 - Insane
2
请将这个答案视为评论,因为它不是对已发布答案的解决方案或增强。 - ckruczek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接