相当于for循环的C memmove-segfault

时间:2018-09-15 23:42:17

标签: c segmentation-fault buffer memmove

我正在使用动态调整大小来实现环形缓冲区。当尾部位于头部之后时,必须将调整后的缓冲区末尾的数据移至新的缓冲区末尾。为此,我编写了以下代码:

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。这两段代码有何不同?

1 个答案:

答案 0 :(得分:1)

仅在sizeof(*self->broadcaster.events) == 1时等效。

为清楚起见,我将self->broadcaster替换为b,并将events替换为e,并在代码中添加了一些空格。

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]的地址前进{{ 1}}个字节。

如果您定义宏,将为您提供最好的服务:

sizeof *b.e

并使用它代替#define MOVE(dst, src, count) memmove((dst), (src), (count) * sizeof *(src))

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

memmove