0 段错误原因
说法:程序试图访问其无权访问的内存位置时发生。
说法:一切对虚拟内存的越权访问,都会导致段错误:
1、试图访问没有映射到物理内存的虚拟内存。
2、试图以非法方式访问虚拟内存(代码区/只读常量区),如对只读内存做写操作等。
1 段错误演示
1.1 演示1
//segmentationFault1 段错误演示1
#include<stdio.h>
int main(void){
int *p = (int*)0x12345678; // (int*)强转,0x12345678由整数变为地址
printf("p = %p\n);
return 0;
}
//编译执行结果如下:
$p = 0x12345678
$
//不报错的原因是,程序只调用了p的值0x12345678,
//并未访问p指向的0x12345678这个虚拟地址
1.2 演示2
//segmentationFault2 段错误演示2
#include<stdio.h>
int main(void){
int *p = (int*)0x12345678;
printf("p = %p\n);
*p = 108; //第1条,试图访问没有映射到物理内存的虚拟内存。
return 0;
}
//编译执行结果如下:
$p = 0x12345678
$段错误(核心已转储)
$
//段错误的原因是,程序要将108这个值存储到p指向的虚拟地址0x12345678,
//发现该虚拟地址并没有对应的物理地址。
1.3 演示3
//segmentationFault3 段错误演示3
#include<stdio.h>
int main(void){
const int i = 0; //i是非静态局部变量,在栈区,不在代码区/只读常量区,有机可乘(甩掉const)。
//i = 1; //编译不过。const修饰的变量,只读,不能(直接)改
*(int*)&i = 1; //&i得到const int*类型,强转成int*类型(甩掉const)后解引用,瞒天过海。
printf("i = %d\n",i);
return 0;
}
//编译执行结果如下:
$i = 1
$
//正常执行,不报错的原因是,
//第2条中的只读内存,指的是代码区/只读常量区的存储区内容,本例中const int i=0;
//i在函数内部,属于非静态局部变量,在栈区,不在代码区/只读常量区,
//通过间接方法还是可以瞒天过海修改滴。
1.4 演示4
//segmentationFault4 段错误演示4
#include<stdio.h>
int main(void){
const static int i = 0; //i是常静态(局部)变量,在代码区/只读常量区,真·只读。
//i = 1; //编译不过。const修饰的变量,只读,不能改
*(int*)&i = 1; //&i得到const int*类型,强转成int*类型(甩掉const)后解引用,瞒天过海·无效。
printf("i = %d\n",i);
return 0;
}
//编译执行结果如下:
$段错误(核心已转储)
$
//段错误的原因是,犯了第2条,
//第2条中的只读内存,指的是代码区/只读常量区的存储区内容,
//真·只读,不能改,本例i就是;