我试图在C++中不存在的目录中打开一个文件,但由于某种原因,我的应用程序没有崩溃。我觉得这有点"奇怪",因为我习惯了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 ipsumn";
f.close();
printf("all goodn");
}
$ 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 ipsumn");
fclose(fl);
printf("all goodn");
}
$ gcc main.c -o main
$ ./main
Segmentation fault (core dumped)
为什么?
我习惯了C",但随后">[...]在C++" - 好吧,C++
不是C
,但这在这里无关紧要。首先,看看这个 - 在设置故障位后,对未打开的流的写入(这里就是这种情况(将被忽略。
但是,在您的C
示例中,问题是如果fopen
fais,它会返回一个NULL
指针。然后你把它传递给fprintf
.这就是未定义行为1发生的地方。在C++
的例子中没有这样的事情。
1请注意,C
示例不能保证SEGFAULT。未定义的行为是未定义的。
使用函数的文档是关键。在这两种情况下,程序都无法打开文件。但是C++库的概念不允许它在构造函数中崩溃,这是有原因的。ofstream
实际上使用相同的fopen
或类似的功能。 让我们看看手册是怎么说的:
成功完成后 fopen((, fdopen(( 和 freopen(( 返回一个 文件指针。 否则,返回 NULL 并将 errno 设置为 指示错误。
所以你必须检查返回的值是否为NULL,否则你有一个未定义的行为。ofstream
为您执行此操作,则在对象初始化期间不会发生未定义的行为。