首页 > 解决方案 > C memmove 相当于 for 循环 - segfault

问题描述

我正在实现具有动态调整大小的环形缓冲区。当 tail 在 head 之后时,缓冲区末尾的数据必须在调整大小后移动到缓冲区的新末尾。为此,我编写了以下代码:

memmove(self->broadcaster.events+self->broadcaster.events_head+self->broadcaster.events_size,
              self->broadcaster.events+self->broadcaster.events_head,
              self->broadcaster.events_size-self->broadcaster.events_head);

self->broadcaster.events_size旧尺寸(new_size/2)在哪里。不幸的是,它会导致分段错误。我认为它相当于这段代码:

for (i = 0 ; i < self->broadcaster.events_size - self->broadcaster.events_head ; ++i)
        self->broadcaster.events[self->broadcaster.events_size+self->broadcaster.events_head+i]=
            self->broadcaster.events[self->broadcaster.events_head+i];

但是这种幼稚的for循环实现可以正常工作,所以我似乎不知道如何memmove正确使用。这两段代码有何不同?

标签: csegmentation-faultbuffermemmove

解决方案


它们仅在sizeof(*self->broadcaster.events) == 1.

为清楚起见,我已替换self->broadcasterbeventse在您的代码中添加了一些空格。

memmove(b.e + b.e_head + b.e_size, b.e + b.e_head, b.e_size - b.e_head);

将只复制b.e_size - b.e_head字节和循环:

for (i = 0 ; i < b.e_size - b.e_head ; ++i)
        b.e[b.e_size + b.e_head + i] = b.e[b.e_head + i];

将复制(b.e_size - b.e_head) * sizeof *b.e字节,因为每个b.e[...] = b.e[...]分配都在字节中移动sizeof *b.e,并且每个都将++i地址推进字节。b.e[... + i]sizeof *b.e

如果你定义一个宏,你会得到最好的服务:

#define MOVE(dst, src, count)  memmove((dst), (src), (count) * sizeof *(src))

并使用它代替memmove.

但是您当然可以将 to 的最后一个参数更改memmove

(self->broadcaster.events_size-self->broadcaster.events_head)*sizeof*self->broadcaster.events

推荐阅读