c - 使用 memcpy() 将缓冲区的尾部移动到其开头? (重叠)

标签 c buffer memcpy

我有二进制文件读取缓冲区,它读取可变长度的结构。在缓冲区末尾附近总会有不完整的结构。我想将这样的缓冲区尾部移动到它的开头,然后在下一次读取文件时读取 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 很小而 buffer 很大,因为这样 memcpy 很可能 不会在单个过程中重叠复制的内存段复制迭代。然而,当尾部变大时听起来有点冒险——大于缓冲区的 50%。

如果 buffer 真的很大并且 tail 也很大那么它仍然应该没问题,因为在单个操作中可以复制多少数据存在物理限制,如果我没记错的话对于使用 vector 单元的现代 x86_64 CPU 来说是 512 字节。我考虑过添加条件来检查尾部的长度,如果它与缓冲区的大小相比太大,则执行简单的逐字节复制,但问题是:

多大太大大到考虑这种重叠memcpy或多或少是安全的。 tail > 缓冲区大小 - 2kb?

最佳答案

根据标准,如果源区域和目标区域重叠,memcpy() 具有未定义的行为。区域有多大或有多少重叠并不重要。未定义的行为永远不能被认为是安全的。

如果您正在编写一个特定的实现,并且该实现定义了某些此类复制的行为,并且您不关心可移植性,那么您可以在这方面依赖您的实现的特定行为。但我建议不要。那将是一个讨厌的错误等待咬那些决定将代码与其他实现一起使用的人。甚至 future 的你。

在这种特殊情况下,可以选择使用专用于此目的的 memmove(),这使得使用 memcpy() 进行赌博变得非常鲁莽。

关于c - 使用 memcpy() 将缓冲区的尾部移动到其开头? (重叠),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50401263/

相关文章:

c - 二维字符数组太大退出代码 139

c++ - 将缓冲区写入文件(存储 1585 字节而不是 1580)

带模板的 C++ 数据包生成器

C Glib GIO - 如何异步列出文件

C警告: control reaches end of non-void function + struct questions

c++ - libcurl 和 DNS ttl 中的内部连接管理

c++ - "Optimal"IO 缓冲 - 程序员 's or Kernel' s 任务?

C中的循环(ring)缓冲区写入方法

c++ - 大小如何与 memcpy 一起使用?

C++ 使用 memcpy 填充结构中的 vector