我有一个程序,我希望它会崩溃,但事实并非如此。你能告诉我原因吗?
char a[5];
strncpy(a,"abcdefg",7);
a[7] = '\0';
printf("%s\n",a);
程序不应该strncpy()
在a[7]='\0'
大于5
. 我得到输出为abcedefg
. 我正在使用 gcc 编译器。
数组的大小为 5 char a[5];
,您在第 7 个位置进行分配,这是缓冲区溢出问题,并且代码的行为在运行时未定义。
strncpy(a,"abcdefg",7);
a[7] = '\0';
两者都是错误的,您需要定义数组,如:
#defined size 9 // greater then > 7
char a[size];
注意空字符"abcdefg"
需要 8 个字符。\0
你不能给未定义的行为下定义,因为你试图声明它应该 crash。另一个通常不会崩溃的未定义行为示例是, 和int x = INT_MAX + 1;
. 如果只是巧合,这些可能会在您的系统上运行。这并不能阻止他们对其他系统造成严重破坏!int x = 0; x = x++ + ++x;
考虑一下“无色、绿色的想法疯狂地沉睡”,或者“打字机把大象传给了黑暗”。这些陈述中的任何一个在英语中都有意义吗?你会如何解释它们?这与 C 实现如何处理未定义行为的情况类似。
让我们考虑一下,如果您让我将 42 个鸡蛋放入可以存储至少12 个鸡蛋的纸箱中会发生什么。容器肯定有界限,但你坚持认为它们都可以放进去。我发现容器只能存放 12 个鸡蛋。你不会知道剩下的 30 个鸡蛋会发生什么,所以行为是不确定的。
在您的示例中,您的程序可以访问超出a
(数组的起始地址)加上 5 的内存,因为程序的堆栈可能更高。因此,尽管代码有效,但理想情况下它是未定义的行为。
C 经常假设您知道自己在做什么,即使(尤其是)您做错了什么。数组没有边界,如果幸运并且您输入了未定义的内存位置并出现分段错误,您只会收到错误消息。否则,您将能够访问更改内存,无论结果如何。