История вопроса
Безопасное копирование памяти — одна из самых частых и критичных задач в C. Первоначально программы использовали цикл для побайтного копирования. Позже были добавлены стандартные функции: memcpy, memmove, а также более защищённые альтернативы вроде strncpy для строк. Неправильное копирование приводит к переполнениям буфера и уязвимостям.
Проблема
Использование неподходящей функции или неверного размера при копировании может разрушить данные или даже открыть путь интересующимся безопасности сторонним лицам. Отличить случаи, когда используется memmove, а когда допустимо memcpy, — принципиально важно для избегания ошибок с перекрывающейся областью памяти.
Решение
Для безопасного копирования нестроковой памяти используйте:
memcpy(dest, src, n);
memcpy быстро копирует n байт из src в dest, если их области памяти не перекрываются.memmove:memmove(dest, src, n);
Для копирования строк используйте либо strncpy, либо, лучше, модерновые и защищённые альтернативы, если доступны (strlcpy).
Ключевые особенности:
memcpy безопасен только при отсутствии перекрытия src и dest.memmove корректно работает даже с перекрывающимися областями памяти.1. Чем отличается memcpy от memmove и когда какая функция необходима?
memcpy работает очень быстро, но не предназначен для перекрывающихся областей памяти — результат станет непредсказуемым. memmove гарантирует корректное копирование вне зависимости от перекрытия:
int arr[] = {1,2,3,4,5}; // memmove: безопасно копируем с перекрытием memmove(arr+1, arr, 4 * sizeof(int));
2. Безопасно ли использовать strcpy для копирования строки в меньший буфер?
Нет, функция strcpy не проверяет размер буфера назначения. Это часто приводит к переполнению буфера. Лучше воспользоваться strncpy, либо strlcpy (если есть), либо явно контролировать размер:
char dest[5]; strncpy(dest, src, sizeof(dest)-1); // src должен быть короче 5 символов
3. Можно ли использовать memcpy для копирования структур с указателями?
Да, но это копирует только сами указатели, а не данные по тем адресам. Это может привести к ошибкам при работе с памятью и двойному освобождению.
Копируется длинная строка в маленький буфер с помощью strcpy без проверки длины источника. Происходит переполнение буфера, что приводит к уязвимости.
Плюсы:
Минусы:
Используется strncpy или memmove с точным контролем размера, вручную обеспечивается завершающий нулевой символ строки.
Плюсы:
Минусы: