strncpy или strlcpy в моем случае - PullRequest
       21

strncpy или strlcpy в моем случае

14 голосов
/ 08 августа 2011

что я должен использовать, когда хочу скопировать src_str в dst_arr и почему?

char dst_arr[10];
char *src_str = "hello";

PS: моя голова кружится быстрее, чем диск моего компьютера, после прочтения многих вещей о том, как хорошо или плохо равно strncpy иstrlcpy.

Примечание: я знаю, что strlcpy доступен не везде.Это не проблема здесь.

Ответы [ 6 ]

28 голосов
/ 08 августа 2011

strncpy - это никогда правильный ответ, когда строка назначения заканчивается на ноль.strncpy - это функция, предназначенная для использования с незавершенными фиксированной шириной строками.Точнее, его целью является преобразование строки с нулевым символом в конце в строку без фиксированной ширины (путем копирования).Другими словами, strncpy здесь не имеет смысла.

Здесь у вас есть реальный выбор между strlcpy и простым strcpy.

Когда вы хотите выполнить «безопасно»(то есть потенциально усеченное) копирование в dst_arr, правильная функция для использования - strlcpy.

Что касается dst_ptr ... Нет такого понятия, как «копировать в dst_ptr».Вы можете скопировать в память , указанную dst_ptr, но сначала вы должны убедиться, что она куда-то указывает и выделить эту память.Есть много разных способов сделать это.

Например, вы можете просто сделать dst_ptr, чтобы указать на dst_arr, и в этом случае ответ будет таким же, как в предыдущем случае - strlcpy.

Или вы можетевыделите память, используя malloc.Если объем выделенной памяти гарантированно будет достаточным для строки (т. Е. Выделено не менее strlen(src_str) + 1 байт), то вы можете использовать обычный strcpy или даже memcpy для копирования строки.В этом случае нет необходимости и нет причин использовать strlcpy, хотя некоторые люди могут предпочесть его, поскольку это как-то дает им ощущение дополнительной безопасности.

Если вы намеренно выделяете меньше памяти (т.е. вы хотитеваша строка будет усечена), тогда strlcpy станет правильной функцией для использования.

5 голосов
/ 08 августа 2011

strlcpy() безопаснее, чем strncpy(), так что вы также можете использовать его.
Системы, у которых его нет, часто имеют s_strncpy(), который делает то же самое.

Примечание : вы не можете скопировать что-либо в dst_ptr, пока оно не укажет на что-то

2 голосов
/ 08 августа 2011

Я не знал о strlcpy. Я только что нашел здесь , что:

Функции strlcpy () и strlcat () копируют и объединяют строки соответственно. Они разработаны, чтобы быть более безопасными, более последовательными и менее подверженные ошибкам замены для strncpy (3) и strncat (3).

Так швы безопаснее.

Редактировать : полное обсуждение доступно здесь .

Edit2

Я понимаю, что то, что я написал выше, не отвечает на "ваш случай" часть вашего вопроса. Если вы понимаете ограничения strncpy, я думаю, вы можете использовать его и написать хороший код, чтобы избежать его ловушек; но если вы не уверены в своем понимании его границ, используйте strlcpy.

Мое понимание ограничений strncpy и strlcpy заключается в том, что вы можете сделать что-то очень плохое с strncpy (переполнением буфера), и худшее, что вы можете сделать с strlcpy, это потерять один символ в процессе.

1 голос
/ 16 ноября 2017

Вы всегда должны использовать стандартную функцию, которая в данном случае является функцией C11 strcpy_s().Не strncpy(), так как это небезопасно и не гарантирует нулевого завершения.И не только для OpenBSD strlcpy(), поскольку это также небезопасно, и OpenBSD всегда предлагает свои собственные изобретения, которые обычно не превращают его в какой-либо стандарт.

См. http://en.cppreference.com/w/c/string/byte/strcpy

Функция strcpy_s аналогична функции BSD strlcpy, за исключением того, что strlcpy усекает исходную строку, чтобы соответствовать месту назначения (что представляет угрозу безопасности)

  • strlcpy не выполняет все проверки во время выполнениячто strcpy_s делает
  • strlcpy не делает сбои очевидными, устанавливая в качестве адресата пустую строку или вызывая обработчик в случае сбоя вызова.
  • Хотя strcpy_s запрещает усечение из-за потенциальных угроз безопасности, это возможночтобы обрезать строку, используя взамен проверенный границ strncpy_s.

Если в вашей библиотеке C нет strcpy_s, используйте safec lib.https://rurban.github.io/safeclib/doc/safec-3.1/df/d8e/strcpy__s_8c.html

0 голосов
/ 09 августа 2011

вы не должны использовать strncpy и не strlcpy для этого.Лучше использовать

*dst_arr=0; strncat(dst_arr,src_arr,(sizeof dst_arr)-1);

или без инициализации

sprintf(dst_arr,"%.*s",(sizeof dst_arr)-1,src_arr);

dst_arr здесь должен быть массив, а НЕ указатель.

0 голосов
/ 08 августа 2011

Прежде всего, у вашего dst_ptr нет выделенного пространства, и вы не установили его так, чтобы он указывал на другие, поэтому присвоение чего-либо этому может вызвать ошибку сегментации.

Strncpy должен прекрасно работать - просто сделайте:

strncpy(dst_arr, src_str, sizeof(dst_arr));

и вы знаете, что не переполните dst_arr. Если вы используете больший src_str, вам, возможно, придется поставить свой собственный нулевой терминатор в конце dst_arr, но в этом случае ваш источник - <ваше назначение, поэтому он все равно будет дополнен нулями. </p>

Это работает везде и безопасно, поэтому я бы не стал смотреть на что-либо еще, если бы не его интеллектуальное любопытство.

Также обратите внимание, что было бы неплохо использовать не магическое число для 10, чтобы вы знали, что размер соответствует размеру strncpy:)

...