首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >gcc-8 -Wstringop-截断是什么良好的做法?

gcc-8 -Wstringop-截断是什么良好的做法?
EN

Stack Overflow用户
提问于 2018-05-06 09:44:48
回答 7查看 36.7K关注 0票数 38

GCC 8号补充了-Wstringop-truncation警告。来自bug.cgi?id=82944

在GCC 8.0中通过r254630为bug 81117添加的-Wstringop截断警告专门用于突出显示可能意外使用的strncpy函数,该函数从源字符串中截断终止的NUL charcter。请求中这种滥用的例子如下:

代码语言:javascript
复制
char buf[2];

void test (const char* str)
{
  strncpy (buf, str, strlen (str));
}

我收到了和这段代码同样的警告。

代码语言:javascript
复制
strncpy(this->name, name, 32);

warning: 'char* strncpy(char*, const char*, size_t)' specified bound 32 equals destination size [-Wstringop-truncation`]

考虑到this->namechar name[32]name是一个长度可能大于32的char*。如果name大于32,我想将它复制到this->name中并截断它。size_t应该是31岁而不是32岁吗?我很困惑。this->name不是必须终止的.

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2018-05-06 10:33:21

这条信息是想警告你,你正在做的正是你正在做的事情。很多时候,这不是程序员想要的。如果这是您想要的(意思是,您的代码将正确地处理字符数组不会最终包含任何空字符的情况),请关闭警告。

如果您不想或不能在全球范围内关闭它,您可以在本地关闭它,正如@doron所指出的:

代码语言:javascript
复制
#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
}
票数 36
EN

Stack Overflow用户

发布于 2019-10-04 14:02:12

这一新的GCC警告使得strncpy()在许多项目中几乎无法使用:代码评审将不接受代码,这会产生警告。但是,如果strncpy()只用于字符串足够短的字符串,以便它可以写入终止的零字节,那么在开始时将目标缓冲区归零,然后普通的strcpy()将完成相同的任务。

实际上,strncpy()是其中一个函数,它们最好不要放在C库中。当然,它也有合法的用例。但是库设计人员也忘了在标准中加入strncpy()的固定大小字符串感知的对应程序。最重要的这类函数,strnlen()strndup(),只包含在POSIX.1中,也就是在strncpy()创建几十年之后!仍然没有函数,它将strncpy()生成的固定长度字符串复制到具有正确C语义的预分配缓冲区中,即始终写入0-终止字节。其中一项职能可以是:

代码语言:javascript
复制
// 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参数,则不清楚是输出缓冲区的大小还是输入字符串的最大长度(通常是少一个)。

票数 6
EN

Stack Overflow用户

发布于 2018-05-06 09:54:01

很少有使用strncpy的正当理由。这是一个相当危险的功能。如果源字符串长度(没有空字符)等于目标缓冲区大小,那么strncpy将不会在目标缓冲区的末尾添加空字符。因此,目标缓冲区不会被终止。

我们应该在Linux上编写这样的代码:

代码语言:javascript
复制
lenSrc = strnlen(pSrc, destSize)
if (lenSrc < destSize)
    memcpy(pDest, pSrc, lenSrc + 1);
else {
    /* Handle error... */
}

在这种情况下,如果您想要截断副本上的源,但仍然想要一个终止为空的目标缓冲区,那么您可以编写这样的代码:

代码语言:javascript
复制
destSize = 32

sizeCp = strnlen(pSrc, destSize - 1);
memcpy(pDest, pSrc, sizeCp);
pDest[sizeCp] = '\0';

编辑:哦..。如果不强制终止NULL,则strncpy是正确使用的函数。是的,你需要用32而不是31来称呼它。我认为你需要通过禁用它来忽略这个警告..。老实说,我没有很好的答案.

Edit2:为了模仿strncpy函数,您可以编写以下代码:

代码语言:javascript
复制
destSize = 32

sizeCp = strnlen(pSrc, destSize - 1);
memcpy(pDest, pSrc, sizeCp + 1);
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50198319

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档