基于C语言中段错误的问题详解_C 语言

当我在linux下写c语言的时候经常会遇到段错误.
所以就来细究一下.
 
段错误或段违规(segmentation violation)
查看Expert C Programming(Peter Van Der Linden) Pg.156
解释到段错误是由于内存管理单元(MMU)的异常所致,
而该异常则通常是由于解除引用一个未初始化或非法的指针引起.

就是指针正在引用一个并不位于你的地址空间中的地址.
书中的例子

复制代码 代码如下:

int *p = 0; 
*p = 17; 

这里显然 地址0 并不是你程序所在的地址空间 所能得到的
而我在试验的时候 几乎随便给个地址 都是段错误
这也很正常,在运行之前是很难知道系统给你分配的地址空间的.
 
于是我这样测试了一下

复制代码 代码如下:

int *p = 0; 
 int a = 7; 

 printf("a addr is %d\n",&a); 
 scanf("%ld",&p); 

 printf("%d",*p);

由于 变量a的地址肯定在系统给你的程序所分配的地址空间内
所以你按照a的地址 给p赋值
或者小数目的向上下移4的整数倍 都是没问题的
经测试 并无段错误

分析了一下原因
在linux中,当你malloc一段内存的时候 只是拿到了 这段内存的虚拟地址.而这段虚拟地址也名没有实质的映射到物理地址.
而只有当你使用这段内存的时候.系统会申请相应页表映射到相应的物理地址.
而*p直接随意指向一个虚拟地址  而这个虚拟地址并没有实际的物理地址与之映射.
这时候解引用会在MMU发出异常,返回到linux就会给用户报一个段错误.
而如果你定义1个int型变量 这个应该是一个栈地址 内核已经把它映射到一个实际的物理页
你在这个基础上小幅度上下偏移地址.相应的都应该有物理地址与之映射.
自然没有问题.

以上都是自己的个人理解.可能还有不足的地方.
欢迎大家交流指教!

时间: 2024-09-20 00:23:26

基于C语言中段错误的问题详解_C 语言的相关文章

C 语言指针变量的运算详解_C 语言

指针变量保存的是地址,本质上是一个整数,可以进行部分运算,例如加法.减法.比较等,请看下面的代码: #include <stdio.h> int main(){ int a = 10, *pa = &a, *paa = &a; double b = 99.9, *pb = &b; char c = '@', *pc = &c; //最初的值 printf("&a=%#X, pa=%#X, pb=%#X, pc=%#X\n", &

基于C++中常见编译错误的总结详解_C 语言

在日常编码过程中会遇见各种编译错误,本文对常见的编译错误进行分析总结.(基本的编译错误在这里不列举,后续后持续更新) 1.error c101008a解决方法该错误出现在项目升级过程中会出现,比如说项目从vs2008升级到vs2010.解决办法:在项目上点右键,清理(Clean),重新编译,问题解决 2.error C2252解决方法该错误主要在项目从vs2008升级到vs2010出先.error C2252: an explicit instantiation of a template ca

基于C/C++时间函数的使用详解_C 语言

C/C++对时间的操作也有许多值得大家注意的地方.最近,在技术群中有很多网友也多次问到过C++语言中对时间的操作.获取和显示等等的问题.下面,在这篇文章中,笔者将主要介绍在C/C++中时间和日期的使用方法.通过学习许多C/C++库,你可以有很多操作.使用时间的方法.但在这之前你需要了解一些"时间"和"日期"的概念,主要有以下几个:Coordinated Universal Time(UTC):协调世界时,又称为世界标准时间,也就是大家所熟知的格林威治标准时间(Gre

基于C++类型重定义的使用详解_C 语言

这几天工作时碰到一个C++的编译错误(我使用的是Visual C++ 7.0),说是有一个类重复定义,仔细想想我们的这个项目也是做了好几个Release了, 内部代码应该不会有这样的低级错误, 真把类型给重复定义了,检查结果正如我预料的一样. 就这样, 我左右没找到原因,被一个编译错误给卡在那里了.(在我的概念中, 程序错误的等级为:编译错误->链接错误->逻辑错误, 此错误属于最低级 ).这时我仔细看了一下错误提示, 发现重复定义是由于从两个不同的路径包含了同一个头文件而引起的,同事也建议从

基于linux下获取时间函数的详解_C 语言

//-------------------------------------------------------------//asctime(将时间和日期以字符串格式表示)#include<time.h>定义函数char * asctime(const struct tm * timeptr);函数说明asctime()将参数timeptr所指的tm结构中的信息转换成真实世界所使用的时间日期表示方法,然后将结果以字符串形态返回.此函数已经由时区转换成当地时间,字符串格式为:"We

基于C++自动化编译工具的使用详解_C 语言

@echo off  title=HYTradingGateway自动化编译打包工具mode con cols=80 lines=40echo -------------------------------------------------------------echo 使用说明echo.                                                             echo HYTradingGateway自动化编译打包工具.修改echo 使用前提

基于Windows API分解路径问题的详解_C 语言

在很多代码中看到,由于需要获取一个路径字符串中的文件名或者扩展名,很多程序员都用了c库中的字符串查找函数来获取.这样子写得代码很多,也麻烦.其实在VC中,可以用更好的方法来获取.没有什么特别多说明,代码如下: 复制代码 代码如下:     LPTSTR szfileName = new TCHAR[MAX_PATH];     GetModuleFileName(NULL, szfileName , MAX_PATH);     // 获取盘符.文件名.扩展名等信息    wchar_t dri

基于C语言实现shell指令的详解_C 语言

源代码来自于TI开发板在ARM上实现shell命令解析 第一步:构建命令实现函数和命令表1,定义结构体 和命令表 复制代码 代码如下: typedef int (*pfnCmdLine)(int argc, char *argv[]);//*****************************************************************************////! Structure for an entry in the command list tabl

基于C++字符串替换函数的使用详解_C 语言

在C++中,字符串替换有很多方法,这里主要说一下STL里的WString中的替换,虽然WString自带了一个Replace函数,但是只能替换一次,太不好了,因此单独写了个替换函数[函数] 复制代码 代码如下: /**         * @brief   实现字符串替换         * @param   orignStr 源串         * @param   oldStr  查找的串         * @param   newStr  替换的新串         * @return