问题概述
在linux下进行网络编程时,经常调用inet_ntoa()来获取某个ip地址,如果操作不当,很容易造成多个ip地址解析的结果相同,
这样严重的bug主要是指针的错误使用造成的,算是无论初学者还是有经验的开发者也会最容易踩的坑之一
1.inet_ntoa返回的其实是固定的空间地址
结构体中有成员char* .ip1 = inet_ntoa();
之后又给char* .ip2 = inet_ntoa();
虽然.ip不是同一个NULL(指针)了,但是调试发现前面的.ip的值和后面的.ip值一样了,
说明inet_ntoa()确实返回同一个字符地址,才会导致前面的.ip(字符指针)和后面的.ip的值(地址值)相同,只是字符地址指向的变量值改变了,所以前面的.ip指向的变量其实变成了后面的ip变量。
所以,不能随便把指针变量直接赋值为inet_ntoa的返回值,因为返回指针指向的内容是可变的。
2.结构体中指针使用不当造成的问题:
结构体中有成员char* .ip1 、char* ip2,
用字符数组char ip_unique[64] 和strncpy间接获得inet_ntoa()返回的字符串,然后把ip_unique的字符串通过strncpy拷贝给.ip
虽然.ip不是直接指向inet_ntoa返回的同一块内存了,但是调试发现前面的.ip1的值和后面的.ip2值还是一样,
说明strncpy函数的应用还得推敲:
strncpy(.ip,ip_unique,strlen(ip_unique));
上面这个语句实际是把ip_unique指向的字符串,拷贝到.ip指向的内存中,注意,这之前,.ip还是初始化为.ip=NULL
证明.ip1、.ip2是同一个NULL(指针),所以后面的.ip被拷贝值填充,其实也是把前面的.ip指向的内存覆盖。
建议在"要被用来创建结构体数组" 的结构体类型定义中,最好不能定义字符指针!也不能循环初始化所有的字符指针为NULL,否则这会给后面造成数据覆盖。
3.结构体使用指针避免一些坑的方法:
解决方法是,将"要被用来创建结构体数组" 的结构体类型定义的字符指针改为一定长度的字符数组,每个字符数组是单独的个体,循环初始化为{0}
虽然都被初始化为{0},由于{0}不是指针而是常量,即所有.ip指向不同的地址,只是该地址上的变量值都初始化为0,不指向同一个NULL,在后面也不会指向同一块内存。