Chinaunix首页 | 论坛 | 博客
  • 博客访问: 307843
  • 博文数量: 47
  • 博客积分: 2455
  • 博客等级: 大尉
  • 技术积分: 558
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-25 15:43
文章分类

全部博文(47)

文章存档

2016年(2)

2012年(10)

2011年(13)

2010年(1)

2009年(19)

2008年(2)

分类: C/C++

2012-11-23 20:32:53

这两天碰到一个很奇怪的问题, 只在本机的Cygwin上出现过, 而在其他Linux上却没看到过.

内容很简单, 基本上就是

stat(file1, &st1);
stat(file2, &st2);
off_t sz1 = st1.st_size;
off_t sz2 = st2.st_size;

而后用printf显式两个文件的大小罢了:
printf("file1: %lu bytes,  file2: %lu bytes\n", sz1, sz2);

结果在Cygwin上, file1的字节数是正确的, 而file2的字节数总是显示为0. 在其他两台Linux, FreeBSD上则是正常结果, 让我很纳闷.

开始我还想是不是file2的内容没同步到磁盘, 以至于没内容啥的, 于是在每个文件close 文件描述符前还专门调用fsync来同步内容, 但是结果依然如此, 即file2依然为0.

后来才猜想, 也许是sz1和sz2的size大小可能与unsigned long不同. 然后就在GDB中查看了一下, 果然是如此.

在我的Cygwin上off_t是8个字节的, 而unsigned long则是4个字节的. 按照显示的错误结果和我机器小端表示法的特征, 猜测这两个%lu读取的都是sz1中字节的内容. 其中file1用的低4个字节的内容, 而file2用的是高4个字节的内容. 由于文件不大, 高4个字节自然都为0, 于是结果就是显示的file2都为0字节.

在我测试的Linux上, 是64的OS, 其中off_t的类型和unsinged long都是8个字节, 故而都得出了正确的结果.

按此猜想, 将printf改为:
printf("file1: %lu bytes,  file2: %lu bytes\n", (unsigned long)sz1, (unsigned long)sz2);
结果果然正确, 且在各个机器上都得出正确结果. 由于我用到的文件<1GB, 故而这样不会出问题.

这就难怪gcc4.4以上的编译器, 在printf都加入了额外的检查, 当格式中指定类型和实际提供的参数类型不同时, 都会抛出警告, 而这在gcc3中是几乎看不到的. 以往我碰到这种警告时, 都是直接跳过不看, 结果确实有时也碰到了莫名其妙的输出结果, 只是没有深入去查看怎么回事, 错过了发现这个问题的早期机会.

当然, 是否出现这个问题取决于printf的具体实现.
阅读(1224) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~