问题是我为什么要定义字符串的大小(string[]
应该是string[some-number]
)
如果程序如下,它会给我Abort trap: 6
:
#include <stdio.h>
#include <string.h>
int main(void)
{
char buffer1[] = "computer";
char string[]="program";
strcat( buffer1, string );
printf( "buffer1 = %s\n", buffer1 );
}
这是来自http://www.tutorialspoint.com/cprogramming/c_data_types.htm的程序,它可以正常工作:
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[12] = "Hello";
char str2[12] = "World";
char str3[12];
int len ;
/* copy str1 into str3 */
strcpy(str3, str1);
printf("strcpy( str3, str1) : %s\n", str3 );
/* concatenates str1 and str2 */
strcat( str1, str2);
printf("strcat( str1, str2): %s\n", str1 );
/* total lenghth of str1 after concatenation */
len = strlen(str1);
printf("strlen(str1) : %d\n", len );
return 0;
}
错误是什么?即使我在程序中定义了所有字符串大小,我的代码仍会提供Abort trap:6
?
答案 0 :(得分:2)
来自strcat的手册页:
说明 strcat()函数将src字符串附加到dest字符串,覆盖termi- 在dest的末尾命名空字节('\ 0'),然后添加一个终止空字节。该 字符串可能不重叠, dest字符串必须有足够的空间用于结果。如果 dest不够大,程序行为不可预测;缓冲区溢出是一个 攻击安全程序的最佳途径。
当你声明你的字符串时,编译器会为buffer1(resp.string)分配初始字符串的大小为9(相应的8)(包括'\ 0')。
因此,strcat将导致9 - 1 + 8(即16个字节),但只有9个可用。
答案 1 :(得分:1)
strcat
的第一个参数用于存储结果,因此它必须有足够的空间用于连接字符串。
在您的代码中:
char buffer1[] = "computer";
相当于:
char buffer1[9] = "computer";
定义一个char数组,其中只有足够的空间用于字符串"computer"
,但没有足够的空间用于结果。
答案 2 :(得分:1)
char buffer1[] = "computer";
创建一个足以容纳9个字符的缓冲区(strlen(1
的“Hello”+ \0
字节))。如果您再向其中写入数据,那么是未定义的行为(UB)。执行strcat
时会发生这种情况
UB意味着程序可能会崩溃或显示任何行为。你很幸运,UB的程序因为不需要而崩溃,但是如果它至少有一个错误的迹象。大多数情况下,使用UB的程序将继续正常运行,并在您最不期望或想要它们时崩溃。
答案 3 :(得分:1)
您的strcat
缓冲区溢出buffer1
,只能容纳strlen("computer")+1
个字节。省略数组大小并不意味着“动态”数组!当您指定数组的大小时,您可以根据需要保留多个字节:当然,您需要避免缓冲区溢出。
所以,
strcpy(str3, str1);
和
strcat( str1, str2);
是正常的,因为str3
的{{1}}大小足够str1
,而str1
就足够strlen(str1) + strlen(str2) + 1
,即恰好11:5(你好)+5(世界)+ 1(终结者)。选择了神奇的数字12是有原因的,大到足以容纳两个字符串和一个终结符。
C字符串是字符数组,其中最后一个是“null”,'\0'
,即它们是字符数组,其中最后一个是0.这个终结符是必需的,以便字符串相关的函数可以理解字符串结束。
如果在字符串中间发现空字节,则从C字符串函数的角度来看,该字符串将在该点结束。 E.g。
char buffer1[] = "computer\0program";
// array: { 'c', 'o', ... '\0', 'p', 'r', 'o', .., 'm', '\0' }
// ...
printf("%s\n", buffer1);
仅打印computer
。但此时缓冲区将足以容纳计算机和程序,一个终结符(和另一个额外的字节),因为编译器计算了char数组的大小,考虑到字符的字符序列,这些字符在语法上以第二个{{1}结束。 }}
但对于所有C字符串函数,"
中包含的字符串为buffer1
。另请注意,computer
将给出正确的缓冲区大小,即17,与sizeof buffer1
的结果相反,后者仅为8。