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

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

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

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

примечание: Я знаю strlcpy не везде доступен. Здесь дело не в этом.

6 ответов


strncpy is никогда правильный ответ, когда строка назначения равна нулю. strncpy - функция, предназначенная для использования с non-terminated фиксированной ширины строки. Точнее, его цель-преобразовать строку с нулевым концом в строку с фиксированной шириной без конца (путем копирования). Другими словами,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 становится правильной функцией для использования.


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

Примечание: вы ничего не можете скопировать в dst_ptr пока это не указывает на что-то


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

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

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

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

Edit2:

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

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


вы всегда должны использовать стандартную функцию, которая в данном случае является C11 . Не 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


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

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

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

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

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

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


вы не должны использовать 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 здесь должен быть массивом, а не указателем.