I'm implementing ring buffer with dynamic resizing. When tail is behind head, data from the end of the buffer has to be moved to new end of buffer after resize. In order to do so I made following code:
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);
where self->broadcaster.events_size
is old size (new_size/2). Unfortunately it results in segmentation fault. I thought it's quivalent of this code:
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];
but such naive for-loop implementation works properly so it seems I don't know how to use memmove
properly. How those two pieces of code are different?
They're only equivalent if sizeof(*self->broadcaster.events) == 1
.
For clarity, I've replaced self->broadcaster
with b
and events
with e
and added some whitespace to your code.
memmove(b.e + b.e_head + b.e_size, b.e + b.e_head, b.e_size - b.e_head);
will copy just b.e_size - b.e_head
bytes, and the loop:
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];
will copy (b.e_size - b.e_head) * sizeof *b.e
bytes, because each b.e[...] = b.e[...]
assignment is moving through sizeof *b.e
bytes, and each ++i
is advancing the address of b.e[... + i]
by sizeof *b.e
bytes.
You'll be best served if you define a macro:
#define MOVE(dst, src, count) memmove((dst), (src), (count) * sizeof *(src))
and use it instead of memmove
.
But you can of course just change the last argument of memmove
to
(self->broadcaster.events_size-self->broadcaster.events_head)*sizeof*self->broadcaster.events