简而言之,产生段错误就是访问了错误的内存段。
一、一般来说,段错误就是指访问的内存超出了系统分配给这个程序的内存空间,通常这个值是由gdtr来保存的,
1)gdtr是一个48位的寄存器,其中的32位是保 存由它指向的gdt表,后13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别。
2)指向的gdt是由以64位为一 个单位的表,在这张表中就保存着程序运行的代码段以及数据段的起始地址以及与此相应的段限和页面交换还有程序运行级别、内存粒度等等的信息。一旦一个程
序发生了越界访问,cpu就会产生相应的异常保护,于是segmentation fault就出现了.
二、在编程中以下几类做法容易导致段错误,基本是是错误地使用指针引起的
1)访问系统数据区,尤其是往系统保护的内存地址写数据:最常见就是给一个指针以0地址2)内存越界(数组越界,变量类型不一致等)访问到不属于你的内存区域
三、解决方法
1)、利用gdb逐步查找段错误:这种方法也是被大众所熟知并广泛采用的方法,首先我们需要一个带有调试信息的可执行程序,所以我们加上“-g -rdynamic"的参数进行编译,然后用gdb调试运行这个新编译的程序,具体步骤如下:gcc -g -rdynamic d.cgdb ./a.out
注:中间省略了一此信息,最后会有如下信息
(gdb) rStarting program: /home/sdd/project/a.outProgram received signal SIGSEGV, Segmentation fault.0x0804860c in main () at main.c:1111 *p=1;从上面我们可以看到出错位置在main.c文件的第11行,其实就是如此的简单。从这里我们还发现进程是由于收到了SIGSEGV信号而结束的。通过进一步的查阅文档(man 7 signal),我们知道SIGSEGV默认handler的动作是打印”段错误"的出错信息,并产生Core文件,由此我们又产生了方法二。
2)、分析Core文件
Core文件是什么呢?The default action of certain signals is to cause a process to terminate and produce a core dump file, a disk file containing an image of the process's memory at the time of termination. A list of the signals which
cause a process to dump core can be found in signal(7).以上资料摘自man page(man 5 core)。 默认情况下,系统禁止了core文件的生成,使用ulimit命令开启,将系统的core文件的大小限制在512K大小,再试:sdd@sdd-desktop:~/project$ ulimit -c0sdd@sdd-desktop:~/project$ ulimit -c 1000sdd@sdd-desktop:~/project$ ulimit -c1000sdd@sdd-desktop:~/project$ ./a.out段错误 (core dumped)sdd@sdd-desktop:~/project$ lsa.out core main.c
core文件终于产生了,用gdb调试一下看看吧:
sdd@sdd-desktop:~/project$ gdb ./a.out core
结果也是一招命中,非常厉害!
3)、下面是别人写得一个程序,在发生了段错误时候自动进行调试,个人感觉非常不错,所以Copy过来了,以备后用。该程序的原理就是对段错误设置自己的处理函数,在发生段错误时,会发出SIGSEGV的信号,通过signal()函数将该信号和自己的处理函数关联。#include #include #include #include
void dump(int signo){char buf[1024];char cmd[1024];FILE *fh;
snprintf(buf, sizeof(buf), "/proc/%d/cmdline", getpid());if(!(fh = fopen(buf, "r")))exit(0);if(!fgets(buf, sizeof(buf), fh))exit(0);fclose(fh);if(buf[strlen(buf) - 1] == ' ')buf[strlen(buf) - 1] = '/0';snprintf(cmd, sizeof(cmd), "gdb %s %d", buf, getpid());system(cmd);
exit(0);}
void dummy_function (void){unsigned char *ptr = 0x00;*ptr = 0x00;}
int main (void){signal(SIGSEGV, &dump);dummy_function ();
return 0;}
作者还给出了一种方法,在此不引用了。帖子的地址贴出来,以备以后查看。
http://edu.codepub.com/2010/0225/20549.PHP
附:ulimit 命令的用法
功能说明:控制shell程序的资源。语 法:ulimit [-aHS][-c ][-d ]
[-f ][-m ][-n ][-p ]
[-s ][-t ][-u ][-v ]补充说明:ulimit为shell内建指令,可用来控制shell执行程序的资源。参 数:-a 显示目前资源限制的设定。-c 设定core文件的最大值,单位为区块。-d 程序数据节区的最大值,单位为KB。-f shell所能建立的最大文件,单位为区块。-H 设定资源的硬性限制,也就是管理员所设下的限制。-m 指定可使用内存的上限,单位为KB。-n 指定同一时间最多可开启的文件数。-p 指定管道缓冲区的大小,单位512字节。-s 指定堆叠的上限,单位为KB。-S 设定资源的弹性限制。-t 指定CPU使用时间的上限,单位为秒。-u 用户最多可开启的程序数目。-v 指定可使用的虚拟内存上限,单位为KB。
http://hi.baidu.com/gruceelee/blog/item/8ba58dce376db08bc8176815.html
我搜这个解决办法主要是我在编程中程序出现了段错误,而我并不知道到底是哪里出了错,我找了我出现段错误的程序进行如上方法调试。
程序不如例程高深,是一个将字符串中数字串输出并找出最大数字串计算其字符个数,然后输出。
版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/meowgi/article/details/53243759
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
发表于 2020-06-28 01:39
阅读 ( 207 )