strncpy (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

Примечания

[править | править код]
  1. the performance implications of strncpy | Nathan's Blog. Дата обращения: 17 октября 2014. Архивировано 18 октября 2014 года.
  2. 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."