在不存在的目录中打开文件 c 与 c++

open a file in a non existing directory c versus c++

我尝试在 C++ 中打开一个不存在的目录中的文件,由于某种原因我的应用程序没有崩溃。我发现有点 "weird" 因为 我习惯了 C,等效程序确实崩溃了 。这是我的 C++ 版本,后面是等效的 C 版本:

$ cat main.cpp
#include <fstream>
int main(int argc, char **argv)
{
    std::ofstream f("/home/oren/NON_EXISTING_DIR/file.txt");
    f << "lorem ipsum\n";
    f.close();
    printf("all good\n");
}
$ g++ main.cpp -o main
$ ./main
all good

当我尝试用 C 做同样的事情时,我得到了一个段错误:

$ cat main.c
#include <stdio.h>
int main(int argc, char **argv)
{
    FILE *fl = fopen("/home/oren/NON_EXISTING_DIR/file.txt","w+t");
    fprintf(fl,"lorem ipsum\n");
    fclose(fl);
    printf("all good\n");
}
$ gcc main.c -o main
$ ./main
Segmentation fault (core dumped)

这是为什么?

"我习惯了C", 但后来"[.. .] 在 C++ 中 " - 好吧,C++ 不是 C,但这与这里无关。首先,看一下 - 在设置 failbit 后,写入未打开的流(这里就是这种情况)将被忽略。

然而,在您的 C 示例中,问题是如果 fopen 失败,它 returns 一个 NULL 指针。然后你将它传递给 fprintf。这就是未定义行为1 发生的地方。 C++ 示例中没有这样的东西。


1请注意 C 示例 不保证 SEGFAULT。未定义的行为是未定义的。

使用函数的文档是关键。在这两种情况下,程序都无法打开文件。但是由于某些原因,C++ 库的概念不允许它在构造函数中崩溃。 ofstream 实际上使用相同的 fopen 或类似的功能。 让我们看看手册是怎么说的:

Upon successful completion fopen(), fdopen() and freopen() return a FILE pointer. Otherwise, NULL is returned and errno is set to indicate the error.

所以你必须检查返回值是否为 NULL,否则你有一个未定义的行为。 ofstream 为您做到了,在对象初始化期间不会发生未定义的行为。