gcc-8 -Wringring-усечение, что является хорошей практикой?

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 быть обнуляемым.

5

Решение

Это сообщение пытается предупредить вас, что вы делаете именно то, что делаете. В большинстве случаев это не то, что задумал программист. Если это именно то, что вы намеревались (имеется в виду, что ваш код будет правильно обрабатывать случай, когда массив символов не будет содержать никаких нулевых символов), отключите предупреждение.

Если вы не хотите или не можете отключить его глобально, вы можете отключить его локально, как указано @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
}
6

Другие решения

Есть очень мало обоснованных случаев использования 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);
2

По вопросам рекламы [email protected]