【问题标题】:fread() fails for some unknown reasonfread() 因某种未知原因而失败
【发布时间】:2013-02-03 18:22:28
【问题描述】:

编辑:当我更改工作目录时它可以工作,因此文件是在不同的目录中创建的。我之前使用的目录唯一奇怪的是它是一个与 VirtualBox 一起使用的共享目录。这一直是 VirtualBox 的错误吗?我最好开始使用单独的目录。

我遇到了一个非常奇怪的问题。在我的程序的某个地方,我有这个代码。我已经对其进行了修改以打印出一些信息来证明问题:

uint8_t section[9];
long pos = ftell(rd);
fseek(rd, 0, SEEK_END);
printf("%li\n",ftell(rd));
fseek(rd, pos, SEEK_SET);
printf("%li\n",ftell(rd));
clearerr(rd);
int i = fread(section, 1, 9, rd);
if (i != 9){
    printf("%i - %i - %i\n",i,feof(rd),ferror(rd));

输出是这样的:

23
14
0 - 0 - 1

所以此时文件的长度为 23,光标为 14。我想要 9 个字节,但 fread 给出零并出现错误。我在 Linux Mint 而不是 OSX 上遇到了这个问题。其他人在debian上似乎没有这个问题。我不知道是什么导致了这个问题。有没有办法进一步诊断错误的原因? ferror() 给出零信息。

文件以“wb+”模式打开。

编辑:

我在 valgrind 中发现了这个晦涩的错误:

==22141== Syscall param write(buf) points to uninitialised byte(s)
==22141==    at 0x5B68900: __write_nocancel (syscall-template.S:82)
==22141==    by 0x5AFB882: _IO_file_write@@GLIBC_2.2.5 (fileops.c:1289)
==22141==    by 0x5AFB749: new_do_write (fileops.c:543)
==22141==    by 0x5AFCEB4: _IO_do_write@@GLIBC_2.2.5 (fileops.c:516)
==22141==    by 0x5AFDD3E: _IO_switch_to_get_mode (genops.c:189)
==22141==    by 0x5AFBA96: _IO_file_seekoff@@GLIBC_2.2.5 (fileops.c:999)
==22141==    by 0x5AF4F25: rewind (rewind.c:37)
==22141==    by 0x567D149: CBFileAppend (CBFileEC.c:69)
==22141==    by 0x5473AFA: CBDatabaseCreateDeletionIndex (CBDatabase.c:270)
==22141==    by 0x5473195: CBInitDatabase (CBDatabase.c:112)
==22141==    by 0x54721A1: CBNewAddressStorage (CBAddressStorage.c:37)
==22141==    by 0x401F67: main (testCBAddressManager.c:226)
==22141==  Address 0x402a009 is not stack'd, malloc'd or (recently) free'd
==22141==  Uninitialised value was created by a stack allocation
==22141==    at 0x546F750: ??? (in /media/sf_BitEagle_Projects/cbitcoin/bin/libcbitcoin-storage.2.0.so)

我不知道在哪里???很明显,所以我没有进一步调试这个的运气。这很奇怪,因为它在 rewind() 中抱怨。

谢谢。

【问题讨论】:

  • 不确定它会改变,但我会做fread(section, 9, 1, rd)...
  • section的定义呢?可能是缓冲区溢出。
  • 我认为 errno 没有设置为读取错误?
  • 我会试试fread(section, 9, 1, rd),因为你永远不知道。
  • 嗯,可能是wb+ 访问:来自手册页 w+ 打开以进行读写。如果文件不存在则创建文件,否则将被截断。 文件可能被截断 - 您是否尝试使用r+ 访问(或rb+)?

标签: c file-io fread


【解决方案1】:

"wb+" 破坏现有文件的内容,根据文档:http://en.cppreference.com/w/c/io/fopen。当您尝试使用“rb+”时,您必须先重新创建文件,否则您会遇到与使用“wb+”打开该文件一样的问题。

编辑:这是您的完整示例代码的样子吗?

int main()
{
  typedef unsigned char uint8_t;

  FILE * rd = fopen("foo.tmp", "wb+");
  uint8_t section[9] = {0};
  long pos = 0;

  fprintf(rd, "01234567890123456789012");

  fseek(rd, 14, SEEK_SET);
  pos = ftell(rd);
  fseek(rd, 0, SEEK_END);
  printf("%li\n",ftell(rd));
  fseek(rd, pos, SEEK_SET);
  printf("%li\n",ftell(rd));
  clearerr(rd);
  int i = fread(section, 1, 9, rd);
  if (i != 9){
    printf("%i - %i - %i\n",i,feof(rd),ferror(rd));
  }

  return 0;
}

【讨论】:

  • 我意识到“wb+”会破坏文件的内容。这正是我想要的(或者我会使用“rb+”)。打开文件后,我将数据写入文件。然后我稍后再阅读这些数据。所以我在这里看不到问题。
  • 我的完整代码是这样的,但没有 printf() 的:github.com/MatthewLM/cbitcoin/blob/master/test/… 那是带有 main() 的文件,但涉及的文件更多。恐怕它不像你的例子。问题代码在:github.com/MatthewLM/cbitcoin/blob/master/dependencies/storage/…
  • 虽然当我想到它时,我猜你的例子会产生相同类型的条件。
  • 嗯,在那种情况下我很难说。乍一看,您的 CBFileSeek() 函数看起来有点奇怪。特别是,似乎试图从位长度转换为字节长度的偏移逻辑。
  • 我的 IO 代码抽象了汉明码纠错和检测。我现在感觉该错误是由堆损坏引起的,因为我有一些未初始化的值问题。
【解决方案2】:

您可能不会相信,但这确实是 VirtualBox 和共享目录的问题。构建过程在普通目录上运行良好。感谢所有试图提供帮助的人。我以前没有使用过 strace,但我会记住这一点!最后我确实得到了 strace-plus 的工作,这可能有一天会证明是有用的。

【讨论】:

    猜你喜欢
    • 2013-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-21
    • 2017-11-22
    • 1970-01-01
    • 2021-09-01
    • 1970-01-01
    相关资源
    最近更新 更多