man strcat
说以下内容。
char *strcat(char *restrict s1, const char *restrict s2);
字符串s1必须有足够的空间来保存结果。
当s1
没有足够的空间时,处理这种情况的正确方法是什么?
如果s1
没有足够的空间来容纳strlen(s1) + strlen(s2) + 1
,尝试使用strcat(s1, s2)
有不确定的行为。
在strcat
中没有内部检查s1
的缓冲区溢出。如果你溢出,你溢出。但是,有一些特定于平台的替代方案,如果正确使用可以降低溢出的风险。作为Windows开发人员,我更喜欢StringCchCat
中的StringCbCat
和<strsafe.h>
。
如果您想保证strcat
的安全,您可以自己包装。就像是:
int safe_strcat(char *s1, char *s2, size_t s1_size)
{
if (strlen(s1) + strlen(s2) + 1 > s1_size)
{
return 0;
}
strcat(s1, s2);
return 1;
}
strcat(s1, s2);
可能导致溢出,因此预防措施“字符串s1必须有足够的空间来保存结果。”是有道理的。
假设s1
可以持有N
字符:N-1
non-'\0'
+ null字符。
当目的地没有足够的空间时,使用
strcat()
的正确方法是什么?
当串联可能溢出时,我看不到使用strcat()
的应用程序。而是使用其他功能。
要检测潜在的溢出:
strlen(s1), strlen(s2)
。
size_t l1 = strlen(s1);
assert(l1 < N); // This really should be true already.
N -= l1;
size_t l2 = strlen(s2);
if (l1 >= N) Handle_TooBigSomehow();
strcpy(s1 + l1, s2);
strncat(char * restrict s1, const char * restrict s2, size_t n)
请注意,这里的n
不是N
:s1
可用的大小。
strncat
函数在n
指向的数组到s2
指向的字符串末尾附加的s1
字符(空字符及其后面的字符不会附加)不超过s2
。s1
的初始字符会覆盖size_t l1 = strlen(s1); assert(l1 < N); // This really should be true already. strncat(s1, s2, N - 1 - l1); // or faster strncat(s1 + l1, s2, N - 1 - l1);
末尾的空字符。终止空字符始终附加到结果。 C11§7.23.3.22
s1
不幸的是,没有明确的迹象表明空间不足,但至少没有溢出,qazxswpoi是空字符终止。
程序员有责任知道s1的大小。如果没有足够的空间,可以调用realloc(s1,num_of_bytes)来分配更多空间。