Способ реализации memcpy
с использованием более чем однобайтовых копий заключается в использовании нестандартного C.
Стандарт C не поддерживает реализацию memcpy
с использованием символов, отличных от типов.
Реализации Quality C предоставляют оптимизированную реализацию memcpy
, которая выполняет эффективное копирование, используя более чем однобайтовые копии, но для этого они используют код, специфичный для реализации. Они могут сделать это, скомпилировав реализацию memcpy
с переключателем, таким как -fnostrict-aliasing
, чтобы сообщить компилятору, что правила псевдонимов будут нарушены в коде, полагаясь на известные особенности конкретной реализации C, чтобы гарантировать, что код будет работать (если вы напишете компилятор, вы можете спроектировать его так, чтобы ваша реализация memcpy
работала), или написав memcpy
на ассемблере.
Кроме того, реализации C могут оптимизировать вызовы memcpy
там, где они появляются в исходном коде, заменяя их прямыми инструкциями для выполнения операции или просто изменяя внутреннюю семантику программы. (Например, если вы скопируете a
в b
, компилятор может вообще не выполнять копирование, а просто загрузиться из a
, где последующий код обращается к b
.)
Чтобы реализовать собственную специализированную операцию копирования с нарушением правил псевдонимов, скомпилируйте ее с помощью -fnostrict-aliasing
, если вы используете GCC или Clang. Если вы используете другой компилятор, проверьте в его документации возможность отключения правил псевдонимов. (Примечание: Apple GCC, который я использую, по умолчанию отключает строгие псевдонимы и принимает -fstrict-aliasing
, но не -fnostrict-aliasing
. Я предполагаю, что не-Apple GCC принимает -fnostrict-aliasing
.)
Если вы используете хорошую реализацию C, вы можете обнаружить, что ваша четырехбайтовая копия реализации memcpy4
не работает так же хорошо, как нативная memcpy
, в зависимости от обстоятельств.
person
Eric Postpischil
schedule
19.01.2014
size
в байтах? Если это так, вам не нужно будет использовать союз; пусть функцияmemcpy4
выполняет копирование, и пусть другие функции обрабатывают свои данные по-своему... Для более широкого типа обратите внимание, чтоint count=size/sizeof(uint32_t);
должно быть достаточно для первой функции. - person abiessu   schedule 19.01.2014#define MY_IMPLEMENTED_COPY_TYPE uint32_t
сделатьint count=size/sizeof(MY_IMPLEMENTED_COPY_TYPE);
, а затем((MY_IMPLEMENTED_COPY_TYPE*)dst)[i] = ((MY_IMPLEMENTED_COPY_TYPE*)src)[i];
- person abiessu   schedule 19.01.2014std::size_t
. Такая реализацияmemcpy()
является классическим примером атаки на основе подписанного целого числа. - person Manu343726   schedule 19.01.2014size /= 4
по-прежнему опасен. Подсказка:sizeof
— ваш друг. - person Bob Jarvis - Reinstate Monica   schedule 19.01.2014uint32_t
. Насколько большойuint32_t
? Я не знаю — я знаю, что я мог бы ДОПОЛНИТЬ, но я не ЗНАЮ — и я абсолютно не знаю ни на одной из платформ. Попробуйтеsize /= sizeof(uint32_t)
. - person Bob Jarvis - Reinstate Monica   schedule 19.01.2014uint32_t
. - person Pascal Cuoq   schedule 19.01.2014sizeof(uint32_t)
обычно равно 4, но может быть меньше на некоторых платформах, гдеCHAR_BIT > 8
. - person Paul R   schedule 19.01.2014uint32_t
определяется как 32 бита, а не 4 байта. Нет требования, чтобы байт был 8-битным, и есть множество платформ, где это не так. - person Mike Seymour   schedule 19.01.2014