[关闭]
@snuffles 2014-12-25T21:28:05.000000Z 字数 1659 阅读 1026

segment fault

程序语言 debug


references:
简单介绍其发生原因的文章
一篇对于每种原因有代码例子的好的文章
知其所以然的一片好文章

今天是历史性的一天,碰到了著名的Segment Fault问题。(怎么办好兴奋,看来我也是坏掉了)。
对于伟大的第一次相遇确实非常简单。确实是访问了空指针,三两句话说一下我的状况。
void getIaq4(IAQ *iaq)函数中有对iaq进行操作的iaq->status=buffer[0], getIaq4(myiaq)函数的调用时候并没有定义函数参数myiaq。


下文来自于第二篇文章的摘抄

一、段错误是什么

段错误是对于软件是老熟人了,总之他就是访问了不让访问的存储器,或者以错误的方式访问了存储器。
段呢,原来是用来管理和维护存储的方式,现在几乎被页方式代替了,但是很多关于段的段子,哦不对是术语仍旧被使用着。段错误就是这样一个例子。在类Unix操作系统,访问无效的内存中的进程收到SIGSEGV信号。
在Microsoft Windows中,访问无效的内存接收STATUS_ACCESS_VIOLATION例外的预警。

二、段错误产生的原因

2.1 访问不存在的内存地址

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. void main()
  4. {
  5. int *ptr = NULL;
  6. *ptr = 0;
  7. }

2.2 访问系统保护的内存地址

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. void main()
  4. {
  5. int *ptr = (int *)0;
  6. *ptr = 100;
  7. }

2.3 访问只读的内存地址

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. void main()
  5. {
  6. char *ptr = "test";
  7. strcpy(ptr, "TEST");
  8. }

2.4 栈溢出

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. void main()
  4. {
  5. main();
  6. }

等等其他原因。

三、段错误信息的获取

dmesg|-g|nm|ldd(本文略、详见references)

四、段错误的调试方法

printf|gcc gdb|core gdb|objdump|catchsegv(本文略、详见references)

可以使用条件编译指令#ifdef DEBUG和#endif把printf函数包起来。这样在程序编译时,如果加上-DDEBUG参数就能查看调试信息;否则不加该参数就不会显示调试信息。

五、一些注意事项


下文来自于第三篇文章的摘抄

提到segment fault经常会说到非法的内存,那就要了解程序的装载过程、原理本文在简单了解进程的内存布局的情况下,从装载的过程入手,深入了解一下Segmetation Fault在操作系统层面是如何产生的,以及程序开发过程中应该如何避免这样的错误。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. int bssvar;
  5. int main(int argc,char** argv)
  6. {
  7. void *ptr;
  8. printf("main start = %p\n",main);
  9. printf("bss end = %p\n",(long)&bssvar+4);
  10. ptr=sbrk(0);
  11. printf("current brk = %p\n",(long*)ptr);
  12. sleep(8);
  13. int i=0x08049628;
  14. brk((char*)0x804A123); //注意这行代码
  15. for(;;i++)
  16. printf("At:0x%x-0x%x\n",i,*((char*)i));
  17. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注