我曾经在中说过: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天功啊, 以后继续坚持学习、实践、总结、分享。好吧, 本文就总结到这里。
有我们特有的记忆,亲情之忆友谊之花爱情之树以及遗憾之泪!