C memmove 相当于 for 循环 - 段错误
C memmove equivalent of for loop - 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
。这两段代码有何不同?
它们只有在 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]
的地址推进sizeof *b.e
字节。
如果你定义一个宏,你会得到最好的服务:
#define MOVE(dst, src, count) memmove((dst), (src), (count) * sizeof *(src))
并用它代替 memmove
。
但是你当然可以把memmove
的最后一个参数改成
(self->broadcaster.events_size-self->broadcaster.events_head)*sizeof*self->broadcaster.events
我正在实施具有动态调整大小的环形缓冲区。当 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
。这两段代码有何不同?
它们只有在 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]
的地址推进sizeof *b.e
字节。
如果你定义一个宏,你会得到最好的服务:
#define MOVE(dst, src, count) memmove((dst), (src), (count) * sizeof *(src))
并用它代替 memmove
。
但是你当然可以把memmove
的最后一个参数改成
(self->broadcaster.events_size-self->broadcaster.events_head)*sizeof*self->broadcaster.events