Почему вы должны использовать strncpy вместо strcpy?



Edit: я добавил источник для примера.

я наткнулся на :

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'nn", 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 );

, который произвел этот выход:

destination is originally = 'abcdefg'
After strcpy, destination becomes '123456789'

destination1 is originally = 'abcdefg'
After strncpy, destination1 becomes '12345fg'

что заставляет меня задаться вопросом, почему кто-то хотел бы этот эффект. Похоже, это будет запутанно. Эта программа заставляет меня думать, что вы можете в основном скопировать чье-то имя (например. Tom Brokaw) с Tom Bro763.

каковы преимущества использованияstrncpy() overstrcpy()?

195   10  

10 ответов:

strncpy борется с переполнением буфера, требуя, чтобы вы поместили в него длину. strcpy зависит от трейлинг -, что может происходить не всегда.

во-вторых, почему вы решили скопировать только 5 символов на 7-символьной строке вне меня, но это производит ожидаемое поведение. Это только копирование над первым n символы, где n - Это третий аргумент.

The n все функции используются в качестве защитного кодирования от переполнения буфера. Пожалуйста, используйте их вместо старых функций, таких как strcpy.

The strncpy() функция была разработана с учетом очень конкретной проблемы: манипулирование строками, хранящимися в виде исходных записей каталога UNIX. Они использовали массив фиксированного размера, и Nul-terminator использовался только в том случае, если имя файла было короче массива.

вот что стоит за двумя странностями strncpy():

  • он не помещает нулевой Терминатор в пункт назначения, если он полностью заполнен; и
  • он всегда полностью заполняет пункт назначения, при необходимости с нулями.

для "безопаснее strcpy()", то вам лучше использовать strncat() вот так:

if (dest_size > 0)
{
    dest[0] = '';
    strncat(dest, source, dest_size - 1);
}

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

в то время как я знаю намерение позади strncpy, Это не очень хорошая функция. Избегайте обоих. Раймонд Чен объясняет.

лично мой вывод состоит в том, чтобы просто избежать strncpy и все его друзья, если вы имеете дело с нулевыми строками. Несмотря на "str" в имени, эти функции не производят строки с нулевым завершением. Они преобразуют строку с нулевым завершением в необработанный символьный буфер. Использование их там, где строка с нулевым завершением ожидается как второй буфер просто неправильный. Мало того, что вы не можете получить правильное нулевое завершение, если источник слишком длинный, но если источник короткий, вы получаете ненужное нулевое заполнение.

см. также почему strncpy небезопасно?

strncpy не безопаснее, чем strcpy, он просто торгует одним типом ошибок с другим. В C, при обработке строк C, вам нужно знать размер ваших буферов, нет никакого способа обойти это. strncpy был оправдан для каталога, упомянутого другими, но в противном случае вы никогда не должны его использовать:

  • Если вы знаете длину строки и буфера, зачем использовать strncpy ? Это пустая трата вычислительной мощности в лучшем случае (добавление бесполезных 0)
  • Если вы не знаете длины, то вы рискуете молча усечь ваши строки, что не намного лучше, чем переполнение буфера

то, что вы ищете-это функция strlcpy() который всегда завершает строку с 0 и инициализирует буфер. Он также способен обнаруживать переполнения. Только проблема, это не (действительно) портативный и присутствует только на некоторых системах (BSD, Solaris). Проблема с этой функцией заключается в том, что она открывает еще одну банку червей, как видно из обсуждений http://en.wikipedia.org/wiki/Strlcpy

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

EDIT: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;
}

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

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

в вашем примере кода index на самом деле не индекс, а count - Он говорит сколько символов максимум для копирования из источника в пункт назначения. Если среди первых n байтов источника нет нулевого байта, строка, помещенная в назначение, не будет завершаться нулем

strncpy заполняет назначение с '\0 ' для размера источника, хотя размер назначения меньше....

manpage:

Если длина src меньше n, strncpy () заполняет остаток dest с нулевыми байтами.

и не только остальные...также после этого до n символов достигнутый. И таким образом вы получаете переполнение... (см. man-страницу реализация)

Это может быть использовано во многих других сценариях, где вам нужно скопировать только часть исходной строки в пункт назначения. С помощью strncpy () вы можете скопировать ограниченную часть исходной строки в отличие от strcpy (). Я вижу, что код, который вы поставили, исходит от publib.boulder.ibm.com.

Это зависит от наших потребностей. Для пользователей Windows

мы используем strncpy всякий раз, когда мы не хотим копировать всю строку или мы хотим скопировать только n количество символов. Но и strcpy копирует всю строку, включая символ null.

эти ссылки помогут вам больше узнать о strcpy и strncpy и где мы можем использовать.

о strcpy

о strncpy

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

    Ничего не найдено.

Добавить ответ:
Отменить.