首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无界误差

无界误差
EN

Stack Overflow用户
提问于 2012-02-04 00:07:53
回答 7查看 35.4K关注 0票数 26

我在C中有这段代码,它包含了一堆char

代码语言:javascript
复制
#include<stdio.h> 
# define NEWLINE '\n'
int main()
{

char c;
char str[6];
int i = 0;
while( ((c = getchar()) != NEWLINE))
{
        str[i] = c;
        ++i;
        printf("%d\n", i);
}

return 0;
}

输入是: testtesttest

产出:1 2 3 4 5 6 7 8 117 118 119 120

我的问题是:

  1. 为什么我不能得到一个越界(分割错误)异常,尽管我显然超过了数组的容量?
  2. 为什么产出中的数字突然跳到很大的数字?

我在C++中尝试了这一点,并得到了同样的行为。有谁能解释一下是什么原因吗?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2012-02-04 00:11:48

  1. C不检查数组边界。只有尝试取消引用指向程序没有访问权限的内存的指针时,才会出现分段错误。仅仅通过数组的末端不太可能导致这种行为。未定义的行为就是--没有定义。它可能看起来很好,但你不应该依赖它的安全。
  2. 通过访问数组结束后的内存,程序会导致未定义的行为。在本例中,您的str[i] = c写操作似乎覆盖了i中的值。
  3. C++具有与C在本例中相同的规则。
票数 32
EN

Stack Overflow用户

发布于 2012-02-04 00:11:14

访问数组索引时,C和C++不执行绑定检查。分段错误仅在尝试读取或写入未分配的页时发生(或尝试在不允许的页面上执行某些操作,例如尝试写入只读页),但由于页面通常相当大(在Mac OS上,倍数为4KB),因此通常会留下大量空间溢出。

如果您的数组位于堆栈上(就像您的数组一样),则可能会更糟,因为堆栈通常相当大(高达几兆字节)。这也是安全问题的原因:写入堆栈上数组的边界可能会覆盖函数的返回地址,并导致任意代码执行(著名的“缓冲区溢出”安全漏洞)。

当你阅读时,你得到的值恰好是在这个特定的地方存在的值。它们是完全未定义的。

如果您使用C++ (并且非常幸运地使用C++11),则标准定义了std::array<T, N>类型,它是一个知道其边界的数组。如果您试图在at方法的末尾进行读取,它将抛出。

票数 6
EN

Stack Overflow用户

发布于 2012-02-04 00:11:38

C不检查数组边界。

实际上,分段错误并不是通过超出数组边界而生成的运行时错误。相反,这是操作系统提供的内存保护的结果。当您的进程试图访问不属于它的内存时,或者当它试图访问不存在的内存地址时,就会发生这种情况。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9137157

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档