strcat Vs strncat - Когда какую функцию следует использовать? - PullRequest
8 голосов
/ 27 июня 2011

Некоторые инструменты статического анализатора кода предлагают заменить все использование strcat на strncat в целях безопасности?

В программе, если мы четко знаем размер целевого буфера и исходных буферов, все еще ли это?рекомендуется использовать strncat?

Кроме того, учитывая рекомендации статических инструментов, следует ли использовать strcat когда-либо?

Ответы [ 5 ]

13 голосов
/ 28 июня 2011

Объединить две строки в одну строку.

Прототипы

#include <string.h>

char * strcat(char *restrict s1, const char *restrict s2);

char * strncat(char *restrict s1, const char *restrict s2, size_t n);

ОПИСАНИЕ

Функции strcat() и strncat() добавляют копию с нулевым символом в конце строка s2 до конца строки s1 с нулевым символом в конце, затем добавьте завершающий символ \ 0 '. Строка s1 должна иметь достаточно места для хранения результат.

Функция strncat () добавляет не более n символов из s2, и затем добавляет завершающий \ 0 '.

Исходная и целевая строки не должны перекрываться, так как поведение не определено.

ВОЗВРАЩАЕМЫЕ ЗНАЧЕНИЯ

 The `strcat()` and `strncat()` functions return the pointer s1.

СООБРАЖЕНИЯ БЕЗОПАСНОСТИ

Функцией strcat() легко злоупотреблять, что позволяет злонамеренным пользователям произвольно изменять функциональность работающей программы. через атаку переполнения буфера.

Избегайте использования strcat(). Вместо этого используйте strncat() или strlcat() и убедитесь, что что в буфер назначения копируется не больше символов, чем может держать.

Обратите внимание, что strncat() также может быть проблематичным. Это может быть проблемой безопасности для строки, которая будет обрезана вообще. Поскольку усеченная строка будет не таким длинным, как оригинал, это может относиться к совершенно другому ресурсу, и использование усеченного ресурса может привести к очень неправильное поведение Пример: * * тысяча сорок восемь

void
 foo(const char *arbitrary_string)
 {
         char onstack[8] = "";

 #if defined(BAD)
         /*
          * This first strcat is bad behavior.  Do not use strcat!
          */
         (void)strcat(onstack, arbitrary_string);        /* BAD! */
 #elif defined(BETTER)
         /*
          * The following two lines demonstrate better use of
          * strncat().
          */
         (void)strncat(onstack, arbitrary_string,
             sizeof(onstack) - strlen(onstack) - 1);
 #elif defined(BEST)
         /*
          * These lines are even more robust due to testing for
          * truncation.
          */
         if (strlen(arbitrary_string) + 1 >
             sizeof(onstack) - strlen(onstack))
                 err(1, "onstack would be truncated");
         (void)strncat(onstack, arbitrary_string,
             sizeof(onstack) - strlen(onstack) - 1);
 #endif
 }

* ** 1052 тысяча пятьдесят один * * Пример 1 053 *

char dest[20] = "Hello";
char *src = ", World!";
char numbers[] = "12345678";

printf("dest before strcat: \"%s\"\n", dest); // "Hello"

strcat(dest, src);
printf("dest after strcat:  \"%s\"\n", dest); // "Hello, World!"

strncat(dest, numbers, 3); // strcat first 3 chars of numbers
printf("dest after strncat: \"%s\"\n", dest); // "Hello, World!123"
11 голосов
/ 27 июня 2011

Если вы абсолютно уверены в размере исходного буфера и в том, что исходный буфер содержит символ NULL, заканчивающий строку, тогда вы можете безопасно использовать strcat, когда целевой буфер достаточно велик.

Я все еще рекомендую использовать strncat и дать ему размер буфера назначения - длина строки назначения - 1

Примечание: я редактировал это, так как комментарии отметили, что мой предыдущий ответ был ужасно неправильным.

1 голос
/ 27 июня 2011

Они не делают то же самое, поэтому они не могут заменить друг друга.Оба имеют разные модели данных.

  • Строка для strcat - это строка с нулевым символом в конце, для которой вы (как программист) гарантируете, что на ней достаточно места.
  • Строка для strncat - это последовательностьchar, который заканчивается либо на длину, указанную вами , либо нулевым окончанием, если предполагается, что он короче этой длины.

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

0 голосов
/ 23 января 2019

Очень просто strcat используется для объединения двух строк, например

String a= data 
String b = structures 

При использовании выполнить strcat

Strcat(a, b) 

тогда

a= data structures

Но если вы хотите объединить определенный номер элемента word r, вы можете использовать strncat Например, если вы хотите объединить только первые два алфавита lts of b в a, тогда вы должны написать Strncat (а, б, 2) (Это означает, что вы просто можете канкатировать первые два алфавита b в a, и a становится а = данные ст

0 голосов
/ 27 июня 2011

Статические инструменты, как правило, плохо понимают обстоятельства, связанные с использованием функции.Могу поспорить, что большинство из них просто предупреждают о каждой встреченной strcat, вместо того, чтобы реально посмотреть, являются ли данные, переданные в функцию, детерминированными или нет.Как уже упоминалось, если у вас есть контроль над входными данными, ни одна из функций небезопасна.

Хотя обратите внимание, что strncat () немного медленнее, поскольку он должен проверять завершение '\ 0' и счетчик, а также явно добавлять его в конец.С другой стороны, strcat () просто проверяет наличие '\ 0' и добавляет завершающий '\ 0' к новой строке, копируя терминатор из второй строки вместе со всеми данными.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...