GCC 8号补充了-Wstringop-truncation警告。来自bug.cgi?id=82944:
在GCC 8.0中通过r254630为bug 81117添加的-Wstringop截断警告专门用于突出显示可能意外使用的strncpy函数,该函数从源字符串中截断终止的NUL charcter。请求中这种滥用的例子如下:
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是一个长度可能大于32的char*。如果name大于32,我想将它复制到this->name中并截断它。size_t应该是31岁而不是32岁吗?我很困惑。this->name不是必须终止的.
发布于 2018-05-06 10:33:21
这条信息是想警告你,你正在做的正是你正在做的事情。很多时候,这不是程序员想要的。如果这是您想要的(意思是,您的代码将正确地处理字符数组不会最终包含任何空字符的情况),请关闭警告。
如果您不想或不能在全球范围内关闭它,您可以在本地关闭它,正如@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
}发布于 2019-10-04 14:02:12
这一新的GCC警告使得strncpy()在许多项目中几乎无法使用:代码评审将不接受代码,这会产生警告。但是,如果strncpy()只用于字符串足够短的字符串,以便它可以写入终止的零字节,那么在开始时将目标缓冲区归零,然后普通的strcpy()将完成相同的任务。
实际上,strncpy()是其中一个函数,它们最好不要放在C库中。当然,它也有合法的用例。但是库设计人员也忘了在标准中加入strncpy()的固定大小字符串感知的对应程序。最重要的这类函数,strnlen()和strndup(),只包含在POSIX.1中,也就是在strncpy()创建几十年之后!仍然没有函数,它将strncpy()生成的固定长度字符串复制到具有正确C语义的预分配缓冲区中,即始终写入0-终止字节。其中一项职能可以是:
// Copy string "in" with at most "insz" chars to buffer "out", which
// is "outsz" bytes long. The output is always 0-terminated. Unlike
// strncpy(), strncpy_t() does not zero fill remaining space in the
// output buffer:
char* strncpy_t(char* out, size_t outsz, const char* in, size_t insz){
assert(outsz > 0);
while(--outsz > 0 && insz > 0 && *in) { *out++ = *in++; insz--; }
*out = 0;
return out;
}我建议为strncpy_t()使用两个长度输入,以避免混淆:如果只有一个size参数,则不清楚是输出缓冲区的大小还是输入字符串的最大长度(通常是少一个)。
发布于 2018-05-06 09:54:01
很少有使用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);https://stackoverflow.com/questions/50198319
复制相似问题