GCC 8 добавил -Wstringop-truncation
предупреждение. От https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82944 :
Предупреждение -Wstringop-truncation, добавленное в GCC 8.0 через r254630 для ошибки 81117, специально предназначено для выделения вероятного непреднамеренного использования функции strncpy, которая усекает завершающий символ NUL из исходной строки. Примером такого неправильного использования, указанного в запросе, является следующий:
char buf[2];
void test (const char* str)
{
strncpy (buf, str, strlen (str));
}
Я получаю то же предупреждение с этим кодом.
strncpy(this->name, name, 32);
warning: 'char* strncpy(char*, const char*, size_t)' specified bound 32 equals destination size [-Wstringop-truncation`]
Учитывая, что this->name
является char name[32]
а также name
это char*
с длиной потенциально больше 32. Я хотел бы скопировать name
в this->name
и обрезать его, если оно больше 32. Должно size_t
быть 31 вместо 32? Я не совсем понимаю. Это не обязательно для this->name
быть обнуляемым.
Это сообщение пытается предупредить вас, что вы делаете именно то, что делаете. В большинстве случаев это не то, что задумал программист. Если это именно то, что вы намеревались (имеется в виду, что ваш код будет правильно обрабатывать случай, когда массив символов не будет содержать никаких нулевых символов), отключите предупреждение.
Если вы не хотите или не можете отключить его глобально, вы можете отключить его локально, как указано @doron:
#include <string.h>
char d[32];
void f(const char *s) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-truncation"strncpy(d, s, 32);
#pragma GCC diagnostic pop
}
Есть очень мало обоснованных случаев использования strncpy
, Это довольно опасная функция. Если длина исходной строки (без нулевого символа) равна размеру целевого буфера, то strncpy
не будет добавлять нулевой символ в конец буфера назначения. Таким образом, буфер назначения не будет нулевым.
Мы должны написать такой код для Linux:
lenSrc = strnlen(pSrc, destSize)
if (lenSrc < destSize)
memcpy(pDest, pSrc, lenSrc + 1);
else {
/* Handle error... */
}
В вашем случае, если вы хотите обрезать источник при копировании, но по-прежнему хотите конечный буфер с нулевым символом в конце, вы можете написать такой код:
destSize = 32
sizeCp = strnlen(pSrc, destSize - 1);
memcpy(pDest, pSrc, sizeCp);
pDest[sizeCp] = '\0';
Редактировать: О … Если это не обязательно для NULL прекращается, strncpy
это правильная функция для использования. И да, вам нужно назвать это с 32, а не 31.
Я думаю, что вы должны игнорировать это предупреждение, отключив его … Честно говоря, у меня нет хорошего ответа на это …
Edit2: для того, чтобы имитировать strncpy
функция, вы могли бы написать этот код:
destSize = 32
sizeCp = strnlen(pSrc, destSize - 1);
memcpy(pDest, pSrc, sizeCp + 1);