Изменить: я добавил источник для примера.
Я наткнулся на такой пример :
char source[MAX] = "123456789";
char source1[MAX] = "123456789";
char destination[MAX] = "abcdefg";
char destination1[MAX] = "abcdefg";
char *return_string;
int index = 5;
/* This is how strcpy works */
printf("destination is originally = '%s'\n", destination);
return_string = strcpy(destination, source);
printf("after strcpy, dest becomes '%s'\n\n", destination);
/* This is how strncpy works */
printf( "destination1 is originally = '%s'\n", destination1 );
return_string = strncpy( destination1, source1, index );
printf( "After strncpy, destination1 becomes '%s'\n", destination1 );
Что произвело этот вывод:
пункт назначения изначально = 'abcdefg' После strcpy пункт назначения становится '123456789' destination1 изначально = 'abcdefg' После strncpy destination1 становится '12345fg'
Это заставляет меня задуматься, зачем кому-то нужен этот эффект. Похоже, это сбивает с толку. Эта программа заставляет меня думать, что вы можете скопировать чье-то имя (например, Том Брокоу) с помощью Tom Bro763.
Какие преимущества использования strncpy()
сверх strcpy()
?
strcpy
вместоstrncpy
?»getline
приведет к неверным результатам, когда я оцениваю их по тщательно подобранным входным данным. :)Ответы:
strncpy
борется с переполнением буфера, требуя, чтобы вы добавили в него длину.strcpy
зависит от трейлинга\0
, который может происходить не всегда.Во-вторых, я не понимаю, почему вы решили копировать только 5 символов в строку из 7 символов, но это дает ожидаемое поведение. Это только копирование первых
n
символов, гдеn
находится третий аргумент.Все
n
функции используются для защиты от переполнения буфера. Пожалуйста, используйте их вместо старых функций, таких какstrcpy
.источник
strncpy
изначально был введен в библиотеку C для работы с полями имени фиксированной длины в таких структурах, как записи каталога. Такие поля не используются так же, как строки: конечный ноль не нужен для поля максимальной длины, а установка конечных байтов для более коротких имен на нуль обеспечивает эффективные полевые сравнения.strncpy
по своему происхождению не является «ограниченной strcpy», и Комитет предпочел признать существующую практику, а не изменять функцию, чтобы она лучше соответствовала такому использованию.strncpy
это не более безопасная версияstrcpy
.strncpy
вместо этого,strcpy
потому что это гораздо более защитная функция ... как я сказал.snprintf
, но не имеет отношенияstrncat
кstrncpy
. Как этот ответ мог получить столько голосов? Это показывает, насколько плоха ситуация с этой фиктивной функцией. Его использование не является защитным: в большинстве случаев программист не понимает его семантику и создает потенциально ненулевую завершающуюся строку.В
strncpy()
Функция была разработана с очень конкретной проблемой в виде: манипуляциях строк , хранящихся в виде исходных записей каталога UNIX. Они использовали массив фиксированного размера, а нулевой символ конца использовался только в том случае, если имя файла было короче, чем массив.Вот что стоит за двумя странностями
strncpy()
:Для «большей безопасности
strcpy()
» лучше использоватьstrncat()
так:if (dest_size > 0) { dest[0] = '\0'; strncat(dest, source, dest_size - 1); }
Это всегда будет обнулять результат и не будет копировать больше, чем необходимо.
источник
dest[0] = '\0';
перед вызовом strncat? Не могли бы вы объяснить, сэр?strncat()
объединяет исходную строку в конец строки назначения. Мы просто хотим скопировать исходную строку в место назначения, поэтому сначала устанавливаем в качестве места назначения пустую строку - вот чтоdest[0] = '\0';
происходит.Хотя я знаю, что за
strncpy
этим стоит, на самом деле это не очень хорошая функция. Избегайте обоих. Раймонд Чен объясняет .См. Также Почему strncpy небезопасен?
источник
strncpy НЕ безопаснее, чем strcpy, он просто заменяет один тип ошибок другим. В C при работе со строками C вам нужно знать размер ваших буферов, нет никакого способа обойти это. strncpy был оправдан для каталога, упомянутого другими, но в противном случае вы никогда не должны его использовать:
источник
То, что вы ищете, - это функция,
strlcpy()
которая всегда завершает строку с 0 и инициализирует буфер. Он также может обнаруживать переполнения. Единственная проблема, он (действительно) не переносимый и присутствует только в некоторых системах (BSD, Solaris). Проблема с этой функцией заключается в том, что она открывает еще одну банку червей, что видно из обсуждений на http://en.wikipedia.org/wiki/Strlcpy.Лично я считаю, что это намного полезнее, чем
strncpy()
иstrcpy()
. Он имеет лучшую производительность и является хорошим компаньономsnprintf()
. Для платформ, на которых его нет, это относительно легко реализовать. (на этапе разработки приложения я заменяю эти две функции (snprintf()
иstrlcpy()
) версией перехвата, которая жестко прерывает программу при переполнении или усечении буфера. Это позволяет быстро отлавливать худших нарушителей. Особенно, если вы работаете с кодовой базой от кого-то другого .РЕДАКТИРОВАТЬ:
strlcpy()
можно легко реализовать:size_t strlcpy(char *dst, const char *src, size_t dstsize) { size_t len = strlen(src); if(dstsize) { size_t bl = (len < dstsize-1 ? len : dstsize-1); ((char*)memcpy(dst, src, bl))[bl] = 0; } return len; }
источник
dstsize > 0
и ничего не делать, если это не так.dstsize
будет запускатьmemcpy
длинуlen
в целевом буфере и переполнять его.Эта
strncpy()
функция более безопасна: вы должны передать максимальную длину, которую может принять целевой буфер. В противном случае может случиться так, что исходная строка неправильно завершится 0, и в этом случаеstrcpy()
функция может записать больше символов в место назначения, повредив все, что находится в памяти после буфера назначения. Это проблема переполнения буфера, используемая во многих эксплойтах.Также для функций POSIX API, таких как
read()
which не помещает завершающий 0 в буфер, но возвращает количество прочитанных байтов, вы либо вручную поместите 0, либо скопируете его, используяstrncpy()
.В вашем примере кода на
index
самом деле это не индекс, аcount
- он сообщает, сколько символов не может быть больше копировать из источника в место назначения. Если среди первых n байтов источника нет нулевого байта, строка, помещенная в пункт назначения, не будет завершена нулемисточник
strncpy заполняет место назначения с помощью '\ 0' для размера источника, хотя размер места назначения меньше ....
страница руководства:
источник
strncpy
заполняет место назначения с помощью '\ 0' для аргумент size, если длина источника меньше. Аргумент размера - это не размер источника, не максимальное количество символов, которое нужно скопировать из источника, поскольку он естьstrncat
, это размер места назначения.strncpy
перед другими операциями копирования заключается в том, что он гарантирует, что будет записан весь адрес назначения. Поскольку компиляторы могут попытаться проявить «творческий подход» при копировании структур, содержащих некоторые неопределенные значения, обеспечение полной записи любых символьных массивов внутри структур может быть самым простым способом предотвратить «сюрпризы».strncpy
чтобы гарантировать нулевое завершение:strncpy(dest, src, dest_size)[dest_size - 1] = '\0';
char[8]
внутри структуры обрабатывать вещи до 8 символов может быть лучше, чем использование,char[8]
но возможность обрабатывать только 7 символов или необходимость копировать строку вchar[9]
буфер, а затемmemcpy
ее в место назначения.char
указатели, пока они не достигнут нуля. В только вещи ноля байт действительно хороши как для строковых литералов, и даже там переменная длиной кодированного префикса, вероятно , будет лучше. Практически для всего остального было бы лучше иметь строки либо с префиксом длины, либо со специальным префиксом, который указывал бы, чтоchar*
это действительно что-то вродеstruct stringInfo {char header[4]; char *realData; size_t length; size_t size;}
.Это можно использовать во многих других сценариях, когда вам нужно скопировать только часть исходной строки в место назначения. Используя strncpy (), вы можете скопировать ограниченную часть исходной строки, в отличие от strcpy (). Я вижу, что код, который вы разместили, взят с сайта publib.boulder.ibm.com .
источник
Это зависит от наших требований. Для пользователей Windows
Мы используем strncpy всякий раз, когда мы не хотим копировать всю строку или хотим скопировать только n символов. Но strcpy копирует всю строку, включая завершающий нулевой символ.
Эти ссылки помогут вам больше узнать о strcpy и strncpy и о том, где мы можем их использовать.
о strcpy
о strncpy
источник
strncpy - это более безопасная версия strcpy, на самом деле вы никогда не должны использовать strcpy, потому что это потенциальная уязвимость переполнения буфера, которая делает вашу систему уязвимой для всех видов атак
источник