在使用Linux环境下使用libpcap开发,在make的时候出现了段错误,用gdb调试发现问题出在以下部分
int
main(int argc,char * argv[]){
.....
pcap_if_t ** alldevsp;
pcap_findalldevs(alldevsp,err_buf);
.....
}
结果:出现 segment fault
然后开始寻找问题,发现时自己对C语言的理解不够深刻
首先
pcap_if_t ** alldevsp;
这个语句定义了一个二级指针alldevsp,这个指针的指向pcap_if_t *类型的一个变量,也就是说,alldevsp这个变量的地址空间中存储的四字节数据的就是一个pcap_if_t *变量的地址
然后观察函数调用
pcap_findalldevs(alldevsp,err_buf);
文档中这个函数数的原型是
int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf);
需要传入一个pcap_if_t ** 类型数据到形参alldevsp
但是凭经验来看,函数对这个参数所作的事情显而易见
官方文档说此函数返回所有网卡描述结构的链表到参数alldevsp
猜测大概的流程是这样的
pcap_if_t * temp = NULL;
temp = getListOfDevs(/);//通过此方法取得链表并返回链表第一个元素的指针
//temp现在指向这个链表的头
*alldevsp = temp;
如果是之前的做法
pcap_if_t ** alldevsp;
pcap_findalldevs(alldevsp,err_buf);
(gcc编译器会给没有生命初始值的变量赋0为初始值)
那就不难看出
现在的形参alldevsp的值是NULL
也就是二级指针变量alldevsp所指向的那个地址(被初始化成NULL)
然后函数中对这个NULL地址进行了*(地址赋值)操作,肯定是出错的啊
所以根本不能这么写
以下是正确写法
pcap_if_t * alldevsp;
pcap_findalldevs(&alldevsp,err_buf);
这个意思就是向函数传入了alldevsp的变量地址,然后经过函数的*操作,向这个地址中赋值,赋得值就是链表头的地址
也就是说alldevsp在调用方法后,就指向了链表头
这样就可以正常进行后续步骤了
。。。。
是的,非常简单的问题,但我当时就是没想起来,说明了学习要注重细节啊,不能一知半解