我有以下代码来打开输入和输出文件:
if ((source_file_ptr = fopen(source_filename, "rb")) == NULL) {
error("unable to open input file");
}
if ((output_file_ptr = fopen(output_filename, "wb")) == NULL) {
error("unable to open output file");
}
这是在打开文件时捕获错误的好简单方法。
然而,在对我的程序进行一些整体编辑后,程序现在崩溃了,而不是捕获无效的输出文件。
我尝试了几件事都没有成功,但有趣的是,当我尝试这个时:
if ((output_file_ptr = fopen(output_filename, "wb")) == NULL) printf("fail");
exit(0);
if ((source_file_ptr = fopen(source_filename, "rb")) == NULL) {
error("unable to open input file");
}
if ((output_file_ptr = fopen(output_filename, "wb")) == NULL) {
error("unable to open output file");
}
它将打印“fail”(并且显然在没有更多洞察力的情况下退出)。
但是如果我注释掉 exit(0) 行,它将再次表现出相同的崩溃行为,而不会打印“失败”,也不会捕获错误。
我无法解释为什么这是...我怀疑是悬空指针,但函数中唯一的前面几行代码已经用大括号括在 if-else if-else 中。上面只声明了几个其他函数,但我已经检查并确保它们都包含在大括号中。
我还在学习 C,对这里发生的事情有什么想法吗?
非常感谢!
注意:用大括号括起 printf("fail") 不会改变我观察到的行为。
编辑:上面的附加代码:
if (fread(&file_struct, sizeof(file_struct), 1, source_file_ptr) < 1) {
error("unable to read %s", source_filename);
}
else {
error_check(file_struct);
if (fwrite(&file_struct, sizeof(file_struct), 1, output_file_ptr) < 1) {
error("unable to write file header");
}
}
最佳答案
我要检查的第一件事是 source_filename
是一个有效的 C 字符串。然后我会以同样的方式检查 output_filename
。
如果事实证明您的更改以某种方式破坏了它们中的一个或两个,那么您将进入未定义的领域行为。
在这里使用调试器是理想的选择,因为您可以在该代码的开头设置一个断点,然后单步执行,检查您将要使用的变量。
您应该检查的另一件事是您对 error
的调用是否实际返回(而不是调用 exit
)。
如果他们这样做了,即使 fopen
调用返回 NULL,您仍会将其传递给 fread
和/或 fwrite
,绝对不能。
由于您的第二个案例打印了 "fail"
,因此可以肯定您在打开输出文件时遇到了一些问题。使用 NULL 句柄并不是一件好事。
如果该函数确实返回,那么您应该使用类似的东西:
if ((source_file_ptr = fopen(source_filename, "rb")) == NULL) {
error("unable to open input file");
return;
}
if ((output_file_ptr = fopen(output_filename, "wb")) == NULL) {
fclose (source_file_ptr);
error("unable to open output file");
return;
}
关于c - 使用 fopen 和测试 NULL 的奇怪 C 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9924148/