strncpy
strncpy — функция стандартной библиотеки языка программирования Си, для копирования содержимого нуль-терминированной строки в буфер ограниченного размера.
Функция strncpy
аналогична strcpy
с защитой от переполнения буфера, однако не является полностью безопасной.
Функция поддерживается всеми компиляторами Си.
Функция
[править | править код]Прототип, описанный в заголовочном файле string.h
:
char *strncpy (char *dst, const char *src, size_t len);
dst
— указатель на буфер назначения.src
— указатель на исходную строку.len
— максимальное количество копируемых символов (см. раздел Безопасность ниже).
Функция копирует из строки src
в буфер dst
не более чем len
символов (включая нулевой символ), не гарантируя завершения строки нулевым символом (если длина строки src
больше или равна len
). Если длина строки src
меньше len
, то буфер добивается до len
нуль- символами.
Возвращаемое значение
[править | править код]Функция возвращает значение dst
.
Пример использования
[править | править код]#include <string.h>
#include <stdio.h> /* для printf() */
int main()
{
char *str = "образец строки";
char buf[10] = {0}; // буфер размером меньше строки
printf("строка: \"%s\"\n\n", str);
printf("буфер перед копированием: \"%s\"\n", buf);
strncpy(buf, str, sizeof(buf) - 1); // len на 1 меньше размера буфера
printf("буфер после копирования: \"%s\"\n", buf);
return 0;
}
Вывод:
строка: "образец строки" буфер перед копированием: "" буфер после копирования: "образец с"
(строка при копировании была урезана до размера буфера — 9 символов + нулевой)
Безопасность
[править | править код]Функция strncpy
призвана защитить программы от переполнения буфера, но сама она также небезопасна по дизайну — функция по стандарту не гарантирует установку нулевого символа в конец буфера, что, при попытке печати строки из буфера (или работы с ней) может привести к чтению данных за пределами буфера, которое приведет к аварийному завершению программы, что можно использовать для проведения сетевой DoS-атаки.
При правильной работе с функцией, нужно передавать в функцию значение len
на единицу меньше размера буфера, а также самостоятельно устанавливать последний байт в 0:
char buf[BUFSIZE]; strncpy(buf, input, sizeof(buf) - 1); buf[sizeof(buf) - 1] = '\0';
Разработчики OpenBSD на замену strncpy
сделали нестандартную функцию strlcpy
, гарантирующую завершение строки нулевым символом. В системах, в которых она также реализована, рекомендуется использовать её, а не strncpy
. В иных системах, возможна кустарная реализация этой функции, из исходного кода, распространяемого по лицензии BSD.
Кроме того, strlcpy
, также, решает проблему производительности strncpy
(см. далее).
Проблема производительности
[править | править код]Стандартное поведение strncpy
неоптимально — функция всякий раз заполняет нулями весь остаток буфера[1][2], что приводит к непроизводительному расходу процессорного ресурса при буфере большого размера и работе с короткими строками (обычная ситуация в сетевых серверах).
Использование вместо strncpy
нестандартной функции strlcpy
или кустарной функции (как, например, в своё время был переписан Apache [1]), может обеспечить существенный прирост производительности (на синтетическом тесте был показан пятикратный прирост [2]).
Внешние ссылки
[править | править код]- strncpy(1) (англ.) — Описание функции
strncpy
на сайте OpenBSD
Примечания
[править | править код]- ↑ the performance implications of strncpy | Nathan's Blog . Дата обращения: 17 октября 2014. Архивировано 18 октября 2014 года.
- ↑ 5.4 Copying and Concatenation Архивировано 21 октября 2014 года. // GNU Libc manual: "Using strncpy .. can also make your program much slower in one common case: copying a string which is probably small into a potentially large buffer. In this case, size may be large, and when it is, strncpy will waste a considerable amount of time copying null characters."