对于内存访问越界的操作在编译时期编译器是不会报错的,而在运行时期有可能发生段错误,有可能不会发生段错误。所以不能根据没有发生段错误来得出内存操作是正确的结论。下面介绍下这样定义的原因。
虚拟内存系统能够操作的最小内存单元是页,每一页有固定的大小,比如4KB。每个页都有可读、可写、可执行的权限。当对一个可读可写的页上的内存进行了越界访问,而没有访问其他的页,则不会产生段错误,而是会改写越界部分的内容。例如:
#include <iostream>
using namespace std;
int main()
{
int arr[3];
int a = 0;
arr[3] = 6;
arr[4] = 9;
cout<<arr[3]<<endl;
cout<<arr[4]<<endl;
cout<<"a = "<<a<<endl;
return 0;
}
在Linux下gcc编译后输出结果是将a的值改写了,没有提示段错误。
在vs2010中会提示段错误,所以不能依赖编译器来检查是否内存操作正确。
在Linux环境下发生段错误的情况:内存越界访问了另一个不存在的页,或者这个页没有读写权限,会提示段错误。
#include <stdio.h>
int main()
{
int arr[3];
int i;
for(i=0; i < 10000; i++)
{
arr[i] = i;
}
return 0;
}
当前页已经写完,超出了操作系统为该程序的数据区域指定的页组范围,当试图再执行写操作时会发生段错误。