JRR*_*JRR 7 c++ gcc strncpy gcc8
海湾合作委员会8增加了-Wstringop-truncation
警告.来自https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82944:
在GCC 8.0中通过r254630为bug 81117添加的-Wstringop-truncation警告专门用于突出显示strncpy函数的非预期用途,该函数截断源字符串中的终止NUL字符.请求中给出的此类滥用的示例如下:
char buf[2];
void test (const char* str)
{
strncpy (buf, str, strlen (str));
}
Run Code Online (Sandbox Code Playgroud)
我用这段代码得到了同样的警告.
strncpy(this->name, name, 32);
warning: 'char* strncpy(char*, const char*, size_t)' specified bound 32 equals destination size [-Wstringop-truncation`]
Run Code Online (Sandbox Code Playgroud)
考虑到this->name
是char name[32]
和name
是一个char*
具有长度可能比32更大我想复制name
成this->name
和截断它,如果它是大于32更大的应该size_t
是31而不是32?我糊涂了.this->name
NUL终止并不是强制性的.
小智 12
这条消息试图警告你,你正在做的正是你正在做的事情.很多时候,这不是程序员的意图.如果它是您的意图(意思是,您的代码将正确处理字符数组最终不包含任何空字符的情况),请关闭警告.
如果您不想或不能全局关闭它,可以按照@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
}
Run Code Online (Sandbox Code Playgroud)
TL;DR:处理截断情况,警告就会消失。
这个警告恰好对我来说非常有用,因为它发现了我的代码中的一个问题。考虑这个清单:
#include <string.h>
#include <stdio.h>
int main() {
const char long_string[] = "It is a very long string";
char short_string[8];
strncpy(short_string, long_string, sizeof(short_string));
/* This line is extremely important, it handles string truncation */
short_string[7] = '\0';
printf("short_string = \"%s\"\n", short_string);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
正如评论所说,short_string[7] = '\0';
这里是必要的。来自strncpy
男人:
警告:如果 src 的前 n 个字节中没有空字节,则放置在 dest 中的字符串不会以空终止。
如果我们删除这一行,它将调用 UB。例如,对于我来说,程序开始打印:
Short_string = "这是一个很长的字符串"
基本上,GCC 希望你修复 UB。我在代码中添加了这样的处理,警告就消失了。
这个新的 GCC 警告strncpy()
在许多项目中几乎无法使用:代码审查将不接受产生警告的代码。但是,如果strncpy()
仅与足够短的字符串一起使用,以便它可以写入终止零字节,则在开始时将目标缓冲区清零,然后将其清零strcpy()
将实现相同的工作。
实际上,strncpy()
是函数之一,最好不要放入C库中。当然,它有合法的用例。但是库设计者忘记将固定大小的字符串感知对应物也strncpy()
放入标准中。最重要的此类函数strnlen()
和strndup()
,仅在 2008 年被包含在 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;
}
Run Code Online (Sandbox Code Playgroud)
我建议为 使用两个长度输入strncpy_t()
,以避免混淆:如果只有一个size
参数,那就不清楚了,它是输出缓冲区的大小还是输入字符串的最大长度(通常少一个) .
归档时间: |
|
查看次数: |
5572 次 |
最近记录: |