免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2907 | 回复: 8
打印 上一主题 下一主题

[C] 关于《C陷阱与缺陷》5.2(P85页)更新顺序文件的疑问 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-06-06 22:16 |只看该作者 |倒序浏览
本帖最后由 聪聪知不道 于 2010-06-06 22:17 编辑

书中提到:
“一个输入操作不能随后直接紧跟一个输出操作,反之亦然。如果要同时进行输入和输出操作,必须在其中插入fseek函数的调用。”
给出的例子是这样的:
  1. 错误的程序
  2. FILE *fp;
  3. fp=fopen(file,"r+");
  4. struct record rec;
  5. ...
  6. while (fread( (char *)&rec, sizeof(rec), 1, fp) == 1){
  7.         /*对rec执行某些操作*/
  8.         if(/*rec必须重新写入*/){
  9.                 fseek(fp, -(long)sizeof(rec), 1);
  10.                 fwrite( (char *)&rec, sizeof(rec), 1, fp);
  11.         }
  12. }
复制代码
作者说这个程序“可能运行失败,而且出错的方式非常难与察觉”,问题出在:“如果一个记录需要被重新写入文件,也就是说,fwrite函数得到执行,对这个文件执行的下一个操作将是循环开始的fread函数。因为在fwrite函数调用与fread函数调用之间缺少了一个fseek函数调用,所以无法进行上述操作。”解决的方法是把这段代码改写为:
  1. while (fread( (char *)&rec, sizeof(rec), 1, fp) == 1){
  2.         /*对rec执行某些操作*/
  3.         if(/*rec必须重新写入*/){
  4.                 fseek(fp, -(long)sizeof(rec), 1);
  5.                 fwrite( (char *)&rec, sizeof(rec), 1, fp);
  6.                 fseek(fp, 0L, 1);
  7.         }
  8. }
复制代码
“第二个fseek函数虽然看上去上那么也没做,但它改变了文件的状态,使得文件现在可以正常的读取了”。

我在Linux2.6内核上用gcc 4.4.3编译运行上面那个“错误的例子”没有发现问题,但是作者书中提到的是“可能运行失败”。那么作者所谓的“可能运行失败”是指的一种什么情况下呢?是否我们现在已经不需要考虑这种失败的情况了呢?

论坛徽章:
0
2 [报告]
发表于 2010-06-06 22:29 |只看该作者
只说明了写那本书的作者用了个垃圾文件系统,ext3/ext4/ntfs无视此类限制。

论坛徽章:
0
3 [报告]
发表于 2010-06-06 22:46 |只看该作者
只说明了写那本书的作者用了个垃圾文件系统,ext3/ext4/ntfs无视此类限制。
没本 发表于 2010-06-06 22:29



作者那个年代用的是啥文件系统呢?
或者说,如果那个文件系统不具备什么样子的性质,就会出现这种“倒霉”结果呢?

论坛徽章:
0
4 [报告]
发表于 2010-06-06 22:55 |只看该作者
回复 3# 聪聪知不道


    比如任地狱Wii游戏机的那个倒霉文件系统。

论坛徽章:
0
5 [报告]
发表于 2010-06-06 23:13 |只看该作者
回复  聪聪知不道


    比如任地狱Wii游戏机的那个倒霉文件系统。
没本 发表于 2010-06-06 22:55



“Wii游戏机”的话,就是说我们今天如果从事某种特殊用途,还是有可能会面对作者的那个“倒霉”问题的吧...

能不能具体说下Wii游戏机用的那个文件系统为什么会有这样的一个问题呢?或者提供个那个文件系统的关键字,我去google也OK

论坛徽章:
0
6 [报告]
发表于 2010-06-06 23:36 |只看该作者
回复 5# 聪聪知不道


    Wii游戏机不开源,如果要看你可以看Wii模拟器,dolphin,有源程序。

论坛徽章:
0
7 [报告]
发表于 2010-06-06 23:46 |只看该作者
回复  聪聪知不道


    Wii游戏机不开源,如果要看你可以看Wii模拟器,dolphin,有源程序。
没本 发表于 2010-06-06 23:36



知道了,谢谢

论坛徽章:
0
8 [报告]
发表于 2012-08-25 00:04 |只看该作者
回复 1# 聪聪知不道


    我在win7_64位,gcc4.45 和vc2010两种环境下测试了这种代码是有问题的(死循环),正在找解答。。

论坛徽章:
12
巳蛇
日期:2013-09-16 15:32:242015年辞旧岁徽章
日期:2015-03-03 16:54:152015年亚洲杯之约旦
日期:2015-02-11 14:38:37双鱼座
日期:2015-01-05 11:05:47戌狗
日期:2014-12-08 09:41:18戌狗
日期:2014-08-15 09:29:29双子座
日期:2014-08-05 09:17:17卯兔
日期:2014-06-08 15:32:18巳蛇
日期:2014-01-27 08:47:08白羊座
日期:2013-11-28 21:04:15巨蟹座
日期:2013-11-13 21:58:012015年亚洲杯之科威特
日期:2015-04-17 16:51:51
9 [报告]
发表于 2012-08-25 11:44 |只看该作者
huangzhenfan 发表于 2012-08-25 00:04
回复 1# 聪聪知不道

这问题最近翻出来好多遍了。

参见APUE上的说法:
当以读和写类型打开一文件时(type中+号),具有下列限制:
a)如果中间没有fflush、fseek、fsetpos或rewind,则在输出的后面不能直接跟随输入。
b)如果中间没有fseek、fsetpos或rewind ,或者一个输出操作没有到达文件尾端,则在输入操作之后不能直接跟随输出。

原因可能和标准输入输出的实现有关。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP