Что такое хорошая практика? - PullRequest
0 голосов
/ 06 мая 2018

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 нет необходимости заканчиваться NUL.

Ответы [ 3 ]

0 голосов
/ 06 мая 2018

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

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

Я обнаружил, что лучший способ подавить предупреждение - поместить выражение в скобки , как этот патч gRPC :

(strncpy(req->initial_request.name, lb_service_name,
         GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH));

Проблема с #pragma решением для подавления диагностики заключается в том, что сама #pragma вызовет предупреждение, когда компилятор не распознает ни прагму, ни конкретное предупреждение; и это слишком многословно.

0 голосов
/ 06 мая 2018

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