在此罗列一些可能导致段错误的地方,以及如何避免相应的错误
出现段错误时,有的很容易调查,但有的很难调查,比如在一个地方把内存写错,需要过一段时间另一个地方读这个内存时,才出错。这种是非常难定位的。因此在编写代码时一定要小心预防。
1 使用非法的指针,包括使用未经初始化及已经释放的指针(指针使用之前和释放之后置为NULL)
2 内存读/写越界。包括数组访问越界,或在使用一些写内存的函数时,长度指定不正确或者这些函数本身不能指定长度,典型的函数有strcpy(strncpy),sprintf(snprint)等等。
3 对于C++对象,请通过相应类的接口来去内存进行操作,禁止通过其返回的指针对内存进行写操作,典型的如string类的data()和c_str()两个接口。
4 函数不要返回其中局部对象的引用或地址,当函数返回时,函数栈弹出,局部对象的地址将失效,改写或读这些地址都会造成未知的后果。
5 避免在栈中定义过大的数组,否则可能导致进程的栈空间不足,此时也会出现段错误。
6 操作系统的相关限制,如:进程可以分配的最大内存,进程可以打开的最大文件描述符个数等,这些需要通过ulimit或setrlimit或sysctl来解除相关的限制。
7 多线程的程序,涉及到多个线程同时操作一块内存时必须进行互斥,否则内存中的内存将不可预料
8 使用非线程安全的函数调用
9 在有信号的环境中,使用不可重入函数调用,而这些函数内部会读或写某片内存区,当信号中断时,内存写操作将被打断,而下次进入时将不避免的出错。
10 跨进程传递某个地址
11 某些有特殊要求的系统调用,例如epool_wait,正常情况下使用close关闭一个套接字后,epool会不再返回这个socket上的事件,但是如果你使用dup或dup2操作,将导致epool无法进行移除操作。