C memmove эквивалент для цикла - Segfault - PullRequest
0 голосов
/ 16 сентября 2018

Я реализую кольцевой буфер с динамическим изменением размера. Когда хвост находится за головой, данные из конца буфера должны быть перемещены в новый конец буфера после изменения размера. Для этого я сделал следующий код:

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-loop работает правильно, поэтому я не знаю, как правильно использовать memmove. Чем эти две части кода отличаются?

1 Ответ

0 голосов
/ 16 сентября 2018

Они эквивалентны только если 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
...