本帖最后由 风信子1314 于 2019-6-25 09:59 编辑
分享一个结构体不匹配 bug 调试过程
前段时间在 lwIP151 版本上对接 RT-Thread Netdev 组件(netdev 组件),因为用到 IPV6 和 IPV4,但当时 netdev 并未支持 IPV6,导致 netdev.h 中的 struct netdev 结构体在 lwip 头文件下和 netdev 头文件下结构体大小不一致。
为什么会有这个问题?请看 netdev 数据结构:
struct netdev
{
rt_slist_t list;
char name[RT_NAME_MAX]; /* network interface device name */
ip_addr_t ip_addr; /* IP address */
ip_addr_t netmask; /* subnet mask */
ip_addr_t gw; /* gateway */
ip_addr_t dns_servers[NETDEV_DNS_SERVERS_NUM]; /* DNS server */
uint8_t hwaddr_len; /* hardware address length */
uint8_t hwaddr[NETDEV_HWADDR_MAX_LEN]; /* hardware address */
uint16_t flags; /* network interface device status flag */
uint16_t mtu; /* maximum transfer unit (in bytes) */
const struct netdev_ops *ops; /* network interface device operations */
netdev_callback_fn status_callback; /* network interface device flags change callback */
netdev_callback_fn addr_callback; /* network interface device address information change callback */
#ifdef RT_USING_SAL
void *sal_user_data; /* user-specific data for SAL */
endif /* RT_USING_SAL */
void *user_data; /* user-specific data */
};
如上,数据结构中包含 ip_addr_t 数据成员,就是该 ip_addr_t 数据结构导致的问题,分析如下:
1. ip_addr_t 数据结构在 netdev 中的定义:
所在头文件 netdev_ipaddr.h
#if NETDEV_IPV4
struct in_addr
{
in_addr_t s_addr;
};
typedef struct ip4_addr
{
uint32_t addr;
} ip4_addr_t;
typedef ip4_addr_t ip_addr_t;
#endif /* NETIF_IPV4 */
2. ip_addr_t 在 lwip 中的定义:
所在头文件:lwip/ip_addr.h
#if LWIP_IPV4 && LWIP_IPV6
/** A union struct for both IP version's addresses.
* ATTENTION: watch out for its size when adding IPv6 address scope!
*/
typedef struct _ip_addr {
union {
ip6_addr_t ip6;
ip4_addr_t ip4;
} u_addr;
u8_t type;
} ip_addr_t;
通过上面两个 ip_addr_t 结构对比,就发现问题了(因为我需要同时支持 IPV4 和 IPV6):
在 lwip 中创建 netdev 设备的时候(ethernetif.c 中创建),使用的是 lwip/ip_addr.h 中的 ip_addr_t,而在 netdev 中使用的是 netdev_ipaddr.h 中的 ip_addr_t,因此两边操作的 netdev 数据结构不一致,导致访问 netdev 数据结构中的数据成员出现莫名奇妙的数据访问错误。
在定位该问题的时候并没有这里写的那么简单,具体过程可以看我博客里的记录。调试过程记录 https://blog.csdn.net/u012349679/article/details/92645870
|