Linux段错误(Segmentation fault)
|字号 订阅
1、段错误的定义
英文:A segmentation fault (often shortened to segfault) is a particular
error condition that can occur during the operation of computer software. In short, a segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not
allowed (e.g., attempts to write to a read-only location, or to overwrite part of the operating system). Systems based on processors like the Motorola 68000 tend to refer to these events as Address or Bus errors.
中文:段错误:访问的内存超出了系统给这个程序的内存空间,通常这个值是由gdtr来保存的,gdtr是一个48位的寄存器,其中的32位是保存由它指向的 gdt表,中间13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的表,在这张表中就保存着程序运行的代码段以及数据段的起始地址以及与此相应的段限和页面交换还有程序运行级别还有内存粒度等等的信息。一旦一个程序发生了越界访问,cpu就会产生相应的异常保护,于是segmentation
fault就出现了。
2、段错误是如何产生的?
Segment fault 之所以能够流行于世,是与Glibc库中基本所有的函数都默认型参指针为非空有着密切关系的。
1)代码1:
#include <stdio.h>
int main(){
int i = 0;
return 0;
}
2)代码2:
#include <stdio.h>
int main(){
}
3)代码3:
#include <stdio.h>
int main(){
printf("%c", test[1000000000]);
return 0;
}
4)代码4:
#include <stdio.h>
int main(){
int b = 10;
return 0;
}
5)代码5:
#include <stdio.h>
#include <string.h>
char c = 'c';
int i = 10;
char buf[100];
printf("%s", c);
出现段错误的原因:试图把char型按照字符串格式输出,这里的字符会解释成整数,再解释成地址,所以原因同上面那个例子printf("%s", i),试图把int型按照字符串输出。
memset(buf, 0, 100);
sprintf(buf, "%s", c);
试图把char型按照字符串格式转换。
memset(buf, 0, 100);
sprintf(buf, "%s", i);
试图把int型按照字符串转换。
6)代码6:
我在进行一个多线程编程的例子里头,定义了一个线程数组
#define THREAD_MAX_NUM
pthread_t thread[THREAD_MAX_NUM];
用pthread_create创建了各个线程,然后用pthread_join来等待线程的结束。
刚开始我就直接等待,在创建线程都成功的时候,pthread_join能够顺利等待各个线程结束,但是一旦创建线程失败,用pthread_join等待那个本不存在的线程时,自然会存在访问不能访问的内存的情况,从而导致段错误。
解决办法为:在创建线程之前,先初始化我们的线程数组,在等待线程的结束的时候,判断线程是否为我们的初始值。如果是的话,说明我们的线程并没有创建成功,所以就不能等,否则就会存在释放那些并不存在或者不可访问的内存空间。