C语言中write()与close()函数的错误处理及测试方法咨询
一、现有代码问题排查
1. write()错误处理问题
- 错误提示输出目标错误:所有程序错误信息默认需要输出到标准错误
STDERR_FILENO,而非标准输出STDOUT_FILENO,这是UNIX类程序的通用规范,你的自动评分系统大概率是校验stderr输出,错误输出到stdout自然无法匹配到预期结果,导致测试不通过。 - 你测试
/dev/full未生效的核心原因也是上述问题:如果把stdout重定向到/dev/full,连你写到stdout的错误信息都会触发写入失败,自然看不到输出,也无法被测试系统捕获。
2. close()错误处理问题
- 错误提示文案错误:当前输出的是
tail: error reading,但这是close调用失败场景,正确文案应该是tail: error closing,明显的文案不匹配会直接导致自动测试判不通过。
二、错误触发测试方法
1. 触发write()错误
方法1:正确使用/dev/full设备
修复错误输出到stderr后,执行如下命令测试,仅将stdout重定向到满设备:
./你的程序名 < 测试输入文件 > /dev/full
此时往stdout写数据会直接返回-1,errno为ENOSPC,对应错误信息就是No space left on device。
方法2:用ulimit限制文件大小
# 限制允许写入的单个文件最大为1字节 ulimit -f 1 # 运行程序写入超过1字节就会触发EFBIG错误 ./你的程序名 < 大体积测试输入 > test_output
2. 触发close()错误
方法1:重复关闭文件描述符
先正常调用close(fd)一次,再调用第二次close(fd),此时会返回-1,errno为EBADF,可以快速验证错误分支逻辑是否走通。
方法2:模拟I/O错误
可以用单元测试打桩的方式,替换close函数的实现,直接让它返回-1并设置errno为EIO,就能得到你需要的Input/output error提示。
如果要真实场景触发,可以用fuse挂载一个自定义故障文件系统,配置为close阶段返回错误即可。
方法3:网络描述符关闭错误
创建TCP socket后,在对端已经主动断开连接的特殊场景下调用close,也有概率触发错误返回。
三、修复后代码参考
write错误处理修复版
for(size_t i = 0;buff[i] != '\0'; i++) { ssize_t j = write(STDOUT_FILENO, &buff[i], 1); if(j == -1) { // 错误信息输出到STDERR const char *prefix = "tail: error writing 'standard output': "; write(STDERR_FILENO, prefix, strlen(prefix)); const char *err = strerror(errno); write(STDERR_FILENO, err, strlen(err)); write(STDERR_FILENO, "\n", 1); return errno; } }
close错误处理修复版
int j = close(fd); if(j == -1) { // 修正错误文案为closing const char *prefix = "tail: error closing '"; write(STDERR_FILENO, prefix, strlen(prefix)); write(STDERR_FILENO, path, strlen(path)); const char *suffix = "': "; write(STDERR_FILENO, suffix, strlen(suffix)); const char *err = strerror(errno); write(STDERR_FILENO, err, strlen(err)); write(STDERR_FILENO, "\n", 1); return errno; }
内容的提问来源于stack exchange,提问作者Inakis Girou
相关产品推荐
相关产品推荐

