我如何故意触发 fgets() 中的错误?
How do I intentionally trigger an error in fgets()?
总结
当使用 fgets()
时,我有错误检查代码,可以在 fgets()
returns null
但尚未到达文件末尾的情况下执行一些补救措施。我想练习这部分代码以验证它是否按预期工作。
是否有一种规范的方式来触发 fgets()
失败?通过手动方式(以某种方式删除调用 fgets()
之间的文件)、一些测试设置(提供有意的 "corrupt" 文件)或其他方法?
最小可复制示例
fgets_fail_test.cpp:
// Test code to show minimally reproducible example of fgets() error handling
// The desire is to manually trigger a failure in fgets()
#include <errno.h>
#include <iostream>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
FILE *fp = fopen("test_file.txt", "r"); //assume this works, not testing this
char buf[100]; //assume large enough to hold data
unsigned int lineno = 1;
while (fgets(buf, 100, fp)) {
std::cout << buf;
lineno++;
}
if (feof(fp)) {
std::cout << "End of file encountered.\n";
}
else if (ferror(fp)) { // how do I trigger an fgets error to cause this to return true?
printf("Encountered read error at line no %u. Error: %d, %s.\n",
lineno,
errno,
strerror(errno));
}
fclose(fp); // assume this works, not testing this
return 0;
}
test_file.txt:
ABCDEFG
HIJKLMN
OPQRSTU
VWXYZ
The quick brown fox
jumped over the
lazy dog.
Goodbye.
理论
虽然我可以简单地用一些测试脚手架替换有问题的代码(编写一个保持内部状态的 fgets 包装器,增加一个计数器,一旦它到达第 #N 行,它 returns null
并手动设置文件错误和错误号)我觉得 应该 有一些 "builtin" 方法来做到这一点?
如果唯一的解决办法是搭建脚手架,我会这样做。老实说,也许我想在这里变得太聪明了。
在一些相关和链接的问题中给出了很多好的答案,这可能会使我的问题重复。虽然我最初搜索时关注的是 fgets()
,但我找不到这些。
一些相关问题是:
- Special File that causes I/O error
- Generate a read error
因为我的程序从具有给定文件名格式的已知文件列表中读取数据,所以我需要使用一种允许我向程序提供错误文件的方法(无需修改代码)。我决定使用 this 答案来做到这一点。
方法
为了生成一个会触发 fgets()
读取失败的错误文件,我利用了 /proc/self/mem
的 "feature",从中读取会导致 I/O 错误。
我删除了我的旧输入文件,并以旧名称链接了一个新文件到 /proc/self/mem
:
ln -s /proc/self/mem test_file.txt
运行 文件然后产生以下输出:
Encountered read error at line no 1. Error: 5, Input/output error.
表示我们触发了错误。感谢@Artyer 的评论,他们最初将我链接到相关问题。
总结
当使用 fgets()
时,我有错误检查代码,可以在 fgets()
returns null
但尚未到达文件末尾的情况下执行一些补救措施。我想练习这部分代码以验证它是否按预期工作。
是否有一种规范的方式来触发 fgets()
失败?通过手动方式(以某种方式删除调用 fgets()
之间的文件)、一些测试设置(提供有意的 "corrupt" 文件)或其他方法?
最小可复制示例
fgets_fail_test.cpp:
// Test code to show minimally reproducible example of fgets() error handling
// The desire is to manually trigger a failure in fgets()
#include <errno.h>
#include <iostream>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
FILE *fp = fopen("test_file.txt", "r"); //assume this works, not testing this
char buf[100]; //assume large enough to hold data
unsigned int lineno = 1;
while (fgets(buf, 100, fp)) {
std::cout << buf;
lineno++;
}
if (feof(fp)) {
std::cout << "End of file encountered.\n";
}
else if (ferror(fp)) { // how do I trigger an fgets error to cause this to return true?
printf("Encountered read error at line no %u. Error: %d, %s.\n",
lineno,
errno,
strerror(errno));
}
fclose(fp); // assume this works, not testing this
return 0;
}
test_file.txt:
ABCDEFG
HIJKLMN
OPQRSTU
VWXYZ
The quick brown fox
jumped over the
lazy dog.
Goodbye.
理论
虽然我可以简单地用一些测试脚手架替换有问题的代码(编写一个保持内部状态的 fgets 包装器,增加一个计数器,一旦它到达第 #N 行,它 returns null
并手动设置文件错误和错误号)我觉得 应该 有一些 "builtin" 方法来做到这一点?
如果唯一的解决办法是搭建脚手架,我会这样做。老实说,也许我想在这里变得太聪明了。
在一些相关和链接的问题中给出了很多好的答案,这可能会使我的问题重复。虽然我最初搜索时关注的是 fgets()
,但我找不到这些。
一些相关问题是:
- Special File that causes I/O error
- Generate a read error
因为我的程序从具有给定文件名格式的已知文件列表中读取数据,所以我需要使用一种允许我向程序提供错误文件的方法(无需修改代码)。我决定使用 this 答案来做到这一点。
方法
为了生成一个会触发 fgets()
读取失败的错误文件,我利用了 /proc/self/mem
的 "feature",从中读取会导致 I/O 错误。
我删除了我的旧输入文件,并以旧名称链接了一个新文件到 /proc/self/mem
:
ln -s /proc/self/mem test_file.txt
运行 文件然后产生以下输出:
Encountered read error at line no 1. Error: 5, Input/output error.
表示我们触发了错误。感谢@Artyer 的评论,他们最初将我链接到相关问题。