亲历fread函数的错误用法及修改验证过程

我曾经在中说过:fwrite和fread函数针对的是字符(无边界), 而不是字符串(以’\0’作为边界)

今天呢, 某模块出了一个问题。 据说, 这个问题搞了较长时间。我准备晚上去打球的,毕竟感觉好久没有打了。 结果一个电话过来, 说有个紧急问题需要我协助定位, 我就乖乖返回了。经了解问题现象并查看源代码, 我立即发现了fread函数用法错误。后来修改并验证, 果然如此。

fread函数错误用法的程序抽象为:

#include <iostream>using namespace std;typedef struct _node{char name[100];int score;}Student;int main(){Student s;memset(&s, 0, sizeof(s));strncpy(s.name, "Eric", sizeof(s.name) – 1);s.score = 99;FILE *fp = fopen("taoge", "w");fwrite(&s, sizeof(s), 1, fp);fwrite(&s, sizeof(s), 1, fp);fwrite(&s, sizeof(s), 1, fp);fclose(fp);Student t;memset(&t, 0, sizeof(t));fp = fopen("taoge", "r");fread(&t, sizeof(t) – 1, 1, fp); // danger, logical errorcout << t.name << endl;cout << t.score << endl;memset(&t, 0, sizeof(t));fread(&t, sizeof(t) – 1, 1, fp); // danger, logical errorcout << t.name << endl;cout << t.score << endl;memset(&t, 0, sizeof(t));fread(&t, sizeof(t) – 1, 1, fp); // danger, logical errorcout << t.name << endl;cout << t.score << endl;fclose(fp);return 0;} 结果为:

Eric99253446488064

我们看到, fread少读了一个字符, 结果会导致后面读取的时候出现整体偏移错误。 应该修改为:

#include <iostream>using namespace std;typedef struct _node{char name[100];int score;}Student;int main(){Student s;memset(&s, 0, sizeof(s));strncpy(s.name, "Eric", sizeof(s.name) – 1);s.score = 99;FILE *fp = fopen("taoge", "w");fwrite(&s, sizeof(s), 1, fp);fwrite(&s, sizeof(s), 1, fp);fwrite(&s, sizeof(s), 1, fp);fclose(fp);Student t;memset(&t, 0, sizeof(t));fp = fopen("taoge", "r");fread(&t, sizeof(t), 1, fp); // okcout << t.name << endl;cout << t.score << endl;memset(&t, 0, sizeof(t));fread(&t, sizeof(t), 1, fp); // okcout << t.name << endl;cout << t.score << endl;memset(&t, 0, sizeof(t));fread(&t, sizeof(t), 1, fp); // okcout << t.name << endl;cout << t.score << endl;fclose(fp);return 0;} 结果:

Eric99Eric99Eric99

正常。

为什么写代码的人当时要用sizeof(…) – 1呢?

根本原因: 没有搞清楚fread函数的用法。在这里, 我再次强调一遍: fread, read, recv, fwrite, write, send这类函数针对的是字符(无边界),, 而不是字符串(以’\0’作为边界), 与’\0’没有半毛钱的关系。

间接原因: 我们经常强调数组szTest必须以’\0’结尾, 可能是当时写该代码的人受了这个思想的影响, 以为任何缓冲区的最后一定是’\0′.

我以前总结过类似问题, 所以今天很快帮助其他同事解决了此问题, 好开心, 尽管最后球没打成。

在其位, 谋其事, 体现自身价值。

台上1分钟, 台下1天功啊, 以后继续坚持学习、实践、总结、分享。好吧, 本文就总结到这里。

有我们特有的记忆,亲情之忆友谊之花爱情之树以及遗憾之泪!

亲历fread函数的错误用法及修改验证过程

相关文章:

你感兴趣的文章:

标签云: