【发布时间】:2018-05-17 22:19:50
【问题描述】:
我有二进制文件读取缓冲区,它读取可变长度的结构。接近缓冲区的末尾总会有不完整的结构。我想将缓冲区的尾部移到它的开头,然后在下一个文件读取期间读取 buffer_size - tail_len 字节。像这样的:
char[8192] buf;
cur = 0, rcur = 0;
while(1){
read("file", &buf[rcur], 8192-rcur);
while (cur + sizeof(mystruct) < 8192){
mystruct_ptr = &buf[cur];
if (mystruct_prt->tailsize + cur >= 8192) break; //incomplete
//do stuff
cur += sizeof(mystruct) + mystruct_ptr->tailsize;
}
memcpy(buf,&buf[cur],8192-cur);
rcur=8192-cur;
cur = 0;
}
应该如果 tail 小而缓冲区大是可以的,因为 memcpy 很可能在单副本迭代期间不会与复制的内存段重叠。然而,当尾巴变大时听起来有点冒险 - 大于缓冲区的 50%。
如果缓冲区真的很大并且尾部也很大,那么它仍然应该没问题,因为在单个操作中可以复制多少数据存在物理限制,如果我没记错的话,对于使用矢量单元的现代 x86_64 CPU 来说是 512 字节。我考虑过添加检查尾部长度的条件,如果它与缓冲区的大小相比太大,则执行简单的逐字节复制,但问题是:
多大太大大到不能考虑这种重叠的memcpy 或多或少是安全的。 tail > buffer size - 2kb?
【问题讨论】:
-
为什么要冒险?如果源区域和目标区域有可能重叠,请使用
memmove()而不是memcpy()。 -
&buf[rcur]也可以写成buf + rcur。您还需要实际检查来自read()的返回值。