写完程序,接下来测试,尽可能地去发现程序中的bugs。我负责一个解析终端协议模块,与同事的业务模块合并在一起。之前,我们就进行过不少的测试,出现最多的的是段错误,SIGSEGV信号,即无效的内存引用。
1.由于同事改了之前我定义数组的长度,导致程序中的数组越界,同时我也没有进行越界检测,程序被迫退出。
2.当只声明对象指针,却没有给予分配内存,引用对象指针内容或对其里面内容赋值时,也出现段错误。
3.由于自己编程习惯不是很好,调用close函数关闭socket文件描述符的时候,我在不同的地方调用了两次释放同样一个描述符,导致内部调用两次free()函数出错
4.客户端在传送数据时突然关闭,服务端就突然无故退出。后来用gdb调试,才发现SIGPIPE信号,因为在客户端关闭后,服务端还在给客户端在send()数据,当管道已经破坏。当时解决是:忽略SIGPIPE信号,调用signal(SIGPIPE,SIG_IGN),且检测管道损坏后,不再往管道发送数据。
5.本来是浮点型,直接乘以1000,转换为长整型,数值失真。后来通过floor函数来解决
对函数的使用不太熟悉,如recv函数
1
| |
6.recv的返回值有正数,0,-1,-2,每一种返回都有其含义,整数代表接收到数据的长度,0代表断开连接,-1代表超时,-2代表错误。对于每一种的返回有其相应的处理。因为当时有个线程没有退出,是因为少考虑了一种情况。其实这个函数有更多的返回。
7.网络上传输的数据不能用strlen函数来得出长度,而应该根据recv函数返回的长度.
8.使用inet_addr()函数是把IP地址转化为网络序,而不是主机序长整形。自己实现函数转换,熟悉位操作。
9.strcpy函数是已经对目标字符串加了’\0’,与字符相关的函数操作strlen,strcmp,strcpy都会用到’\0’判断字符的结束。同时memcpy函数是不加’\0’的,这个是通用的数据复制函数。不单单支持char类型。
10.使用osip库中的API的时候,当出现问题时,要懂得看源码,弄懂它的实现机制。如用两个线程绑定不同的IP的5060端口,在eXosip库是不可以的,因为它的实现里用到一个全局的结构体,后面的会覆盖前面的设置,只有一个IP的5060有效。可能需要两个进程解决,但同时又要解决两个进程的通信问题了。
11.eXosip_call_ack函数发送的ack总是收不到,用wireshark抓包也抓不到,仔细检查过代码后,还是觉得没问题,后来百度了一下,有人提到是网络不通,后来同事辛辛苦苦弄出来了,原来同事的虚拟机安装了virbird的服务,导致网络不通。具体的原因我现在还没清楚,可能同事也是看源码弄清楚,还是挺欣赏同事从库的源代码找思路解决问题的。
12.1 这两天我们的程序又出现破坏堆中内存分配的信息数据的信息:
glibc detected * free(): invalid pointer:
glibc detected * malloc(): memory corruption:
glibc detected * double free or corruption (out): 0x005c18a0 **
glibc detected * corrupted double-linked list: 0x005ab150
12.2 如果破坏了自己的其它对象的内存空间,就可能诱发coredump的错误。
12.3一般出现这些内存问题的原因:
a.使用未初始化的内存(using uninitialized memory.未初始化的内存的垃圾值可能会导致不可预测的错误)
b.内存泄漏,分配的内存忘了释放 ;内存重复释放,出现double free;(faulty heap memory management:内存泄漏,释放空指针或释放未分配的内存)
c.内存越界使用,使用了不该使用的内存(Using beyond allocated memory缓冲溢出,栈保护)
d.使用了无效的指针 (Using un-owned memory,null指针和悬挂或野指针。如多线程中某一动态分配的对象同时被两个线程使用。一个线程释放了该对象,而另一线程还对该对象进行操作)
e.空指针,对一个空指针进行操作
12.4 排查的原则,首先保证能重现错误。根据错误估计可能的环节,逐步裁剪代码,缩小排查空间检查所有的内存操作函数,检查内存越界的可能性。常用的内存操作函数:
字符串输出:sprintf snprintf vsprintf vsnprintf
字符串操作:strcpy strncpy strcat
内存操作:memcpy memmove memset bcopy
12.5排查的工具:gdb(调试器),Purify,Valgrind,Insure++,AddressSanitizer
13.程序中出现:glibc detected * free(): invalid pointer,原来是sip库里函数实现有free,但却无知地传入个数组。应该动态申请内存。