我有以下代码:
# include<stdio.h>
# include<string.h>
# define M 5
void mycopy(char* text)
{
char buffer[M];
strcpy(buffer, text);
}
int main()
{
char *name = "Kshitij";
int i = 0;
mycopy(name);
printf("i = %d", i);
return 0;
}
此代码在Apple LLVM 8.0.0版(clang-800.0.42.1)上的GCC中编译。
但是,当我尝试运行相应的可执行文件时,我得到一个进程abort
输出,例如:
[1] PID abort ./executable.out
我理解错误是预期的,因为buffer
数组的大小小于在这种情况下传递给它的text
参数的长度。但是,我无法理解掌握这种行为背后的概念。为什么编译时错误没有说明编译器在这里引发的原因?
答案 0 :(得分:0)
C11标准在7.1.4. Use of library functions中说明了以下内容:
如果函数参数被描述为数组,*实际传递给函数的指针必须具有一个值,使 所有地址计算和访问对象(如果指针指向这样一个数组的第一个元素则有效)实际上是有效的。
2 strcpy函数将s2指向的字符串(包括终止空字符)复制到s1指向的数组中。
在Appendix J.2 Undefined behavior:
1在以下情况下,行为未定义: 传递给库函数数组参数的指针没有值,所有地址计算和对象访问都是有效的(7.1.4)。
由于行为未定义,根据标准,任何事情都可能发生。编译器实际上是允许进行编译时边界检查,如果可以推断出程序总是写出超出边界,则编译可能会被中止。或者实现可以通过明确的诊断支持范围检查和中止。或者strcpy
可能只复制4个第一个字符并添加终止空值,或者将42
复制到目标字符串中 - 而且所有这些实现都符合标准。