如何在没有缓冲区溢出问题的情况下使用strncat?
我有一个缓冲区,我正在做很多strncat。 我想确保我永远不会溢出缓冲区大小。
char buff[64]; strcpy(buff, "String 1"); strncat(buff, "String 2", sizeof(buff)); strncat(buff, "String 3", sizeof(buff));
而不是sizeof(buff),我想说一些buff – xxx。 我想确保我永远不会覆盖缓冲区
考虑现有字符串和null终止符的大小
#define BUFFER_SIZE 64 char buff[BUFFER_SIZE]; //Use strncpy strncpy(buff, "String 1", BUFFER_SIZE - 1); buff[BUFFER_SIZE - 1] = '\0'; strncat(buff, "String 2", BUFFER_SIZE - strlen(buff) - 1); strncat(buff, "String 3", BUFFER_SIZE - strlen(buff) - 1);
为什么不使用snprintf
? 与strncat
不同,它需要缓冲区的大小,但更重要的是,没有隐藏的O(n)。
Strcat需要在它连接的每个字符串上找到空终止符,并且每次都通过整个缓冲区来查找结束。 每次字符串变长,strcat都会变慢。 另一方面,Sprintf可以跟踪结束。 你会发现的
snprintf(buf, sizeof buf, "%s%s%s", "String1", "String2", "String3");
通常是一个更快,更易读的解决方案。
在你的orignal代码中使用strncat
函数的方式实际上适用于另一个函数: strlcat
(注意l
而不是n
)。 strlcat
函数不是标准函数,但它是strncat
一个流行的实现提供的替代品。 strlcat
期望整个目标缓冲区的总大小作为其最后一个参数。
同时, strncat
期望将目标缓冲区的剩余未使用部分的大小作为其第三个参数。 因此,您的原始代码不正确。
我建议不要使用strncpy
这种可怕的滥用并使用strlen
调用进行显式重新扫描(Joe的答案中都存在这两个问题),你要么使用实现提供的strlcat
要么自己实现(如果你的实现没有提供strlcat
)。
这是最好的方法。 sizeof()
只是给你指向数据的指针的大小,如果你不在本地分配它(在这种情况下你确实在本地分配,但最好这样做,如果代码被重新分解它将起作用)。
#define MAXBUFFSIZE 64 char buff[MAXBUFFSIZE]; buff[0] = 0; // or some string strncat(buff, "String x",MAXBUFFSIZE - strlen(buff) - 1);
霍根已经足够满满地回答了这个问题; 但是,如果你担心strcat(...)
缓冲区溢出,你应该同样担心所有其他字符串函数中的缓冲区溢出。
使用strnlen(...)
和strncpy(...)
来确保您保持在缓冲区内。 如果您没有strnlen(...)
函数,请编写它。