字符串成功打印出来后,但是竟然报这个错:(栈溢出)
*** stack smashing detected ***: ./test terminated
Aborted (core dumped)
结果都已经出来为什么报这个错呢?既然结果已经出来,推测应该不是算法(strnat1)的问题。下面是调用处的代码
int main()
{
char str[] = "1234567";
char str2[] = "abc";
printf("%s\n", strncat1(str, str2, 2));
return 0;
}
str大小是8个元素,调用strncat1后,str就含有10个元素了!栈内存空间就溢出了!(数组写入的时候越界)
为什么能打印出“结果”呢?为什么在打印出结果后报错呢?
C语言比较“宽松、灵活,语法检查不严格”,在遇到数组越界、栈溢出等问题时编译时不会报出来,等到程序运行时才知道有这个错!不,程序运行时也不一定能注意到栈溢出,
就如上面的,虽然越界了,一是没有覆盖掉其它的重要数据,二是,自身也能结束('\0'),所以有可能看不出来!
应对“栈溢出”(也称缓存区溢出),需要一些对策。比如GCC的“Stack-Smashing Protector”机制(在数组后插入一些金丝雀(Canary, 因为大家在矿井作业时,会用金丝雀来预警,如果金丝雀死了,那证明有毒气),在函数执行完成返回之前会检查一下Canary,如果canary被改掉,则不再继续执行,中止程序,避免执行攻击者的代码。)
因此,出现“栈溢出”这个错,实际上是GCC编译器的保护作用!这也是为什么在打印结果之后才报错!
另外,尝试了编译时怎么不开启"Stack-Smashing Protector"。(“Stack-Smashing Protector”默认是打开的!)
如:$ gcc test.c -fno-stack-protector。运行时输出结果后不会报“stack smashing detected”!
或者在函数内增加长度/边界检查,防止越界!