函数重名和结构体出现两种定义
这个Bug是在查另一个Bug时发现的,源Bug暂且按下不表
先说一下大致的情况
struct zebra_client_arg zebra_client
是进程中的一个全局变量,struct zebra_client_arg
的定义如下:
struct zebra_client_arg {
int lc_num;
enum CLIENT_TYPE type;
zebra_client_thread_runtime_t* runtime;
transport_sock_info_t *sock;
struct zebra_client_cb *cb_functions;
struct avl_table *ipv4_info_tree;
struct avl_table *ipv6_info_tree;
struct avl_table *ipv4_neigh_tree;
struct avl_table *ipv6_neigh_tree;
struct avl_table *tunnel_info_tree;
struct avl_table *mpls_info_ilm_tree;
struct avl_table *mpls_vpls_bind_tree;
struct avl_table *mpls_vpls_vc_tree;
struct avl_table *mplsoam_pw_status_tree;
struct avl_table *mvpn_mdt_tree;
struct avl_table *mvpn_mlsp_tree;
struct avl_table *mvpn_cm_route_tree;
struct avl_table *mvpn_ad_route_tree;
};
进程初始化的时候,将zebra_client
通过库函数提供的接口注册到库中
zebra_client.lc_num = getSmmId();
zebra_client.type = SMM_SWITCHMGR;
zebra_client.sock = &client_info;
zebra_client.cb_functions = &switchmgr_callbacks;
for(i = 0; i < LOCK_MAX_NBR; i++) {
CASA_RWLOCK_INIT(pthread_lock_arr[i]);
}
zebra_client_init(&zebra_client, &client_threadid);
在库中完成对ipv4_info_tree
、ipv4_neigh_tree
、mpls_vpls_bind_tree
等的进一步初始化
然后,我们来看一下堆栈
(gdb) bt
#0 ipv6_info_compare (n1=0x33f002a0, n2=0x3ddc, param=0x0) at /vob/jenkins/_build_864_temp/workspace/sdk/src/customer_smm/l3.c:2006
#1 0x0152c4b8 in avl_delete (tree=0x3212c430, item=0x33f002a0) at /vob/jenkins/_build_864_temp/workspace/sdk/src/customer/avl.c:348
#2 0x2ab898f4 in info_tree_mp_delete (info=0x0, type=1, tree=0x33f002a0) at /vob/jenkins/_build_864_temp/workspace/casa/util/casa_util/zebra_remote_client.c:1972
#3 0x2ab8bfb8 in client_parse_msg (buf=<value optimized out>, buf_len=1582, sock_len=<value optimized out>, client=0x43138e0) at /vob/jenkins/_build_864_temp/workspace/casa/util/casa_util/zebra_remote_client.c:3766
#4 0x2ab8d1e8 in zebra_client_main (params=0x43138e0) at /vob/jenkins/_build_864_temp/workspace/casa/util/casa_util/zebra_remote_client.c:4286
#5 0x2ade0d80 in start_thread (arg=<value optimized out>) at pthread_create.c:263
#6 0x2afd0a2c in __thread_start () from /pluto-tftpboot/mlin/LIBC-32bit-RMI/lib/libc.so.6
frame 3 中的client_parse_msg
就是用的主线程中的zebra_client_init
但是,继续看堆栈,在frame 1&2中,调用的zebra_client_init->ipv6_info_tree
的时候跑到主线程里去了,这个指针的初始化明明是在库里的,应该用库里的ipv6_info_compare()
才对
但实际上并没有,因为在主线程里也有这么一个同名函数,导致在加载动态库的时候,这个指针索引到了主线程里的这个函数
解决方案好说,把这两个同名函数定义成静态函数,让他们只在自己的源文件中可见
接下来看另一个问题
在库中查看client->ipv6_info_tree
内容的时候,发现有两个字段明显有问题
(gdb) f
#3 0x2ab8bfb8 in client_parse_msg (buf=<value optimized out>, buf_len=1582, sock_len=<value optimized out>, client=0x43138e0) at /vob/jenkins/_build_864_temp/workspace/casa/util/casa_util/zebra_remote_client.c:3766
3766 in /vob/jenkins/_build_864_temp/workspace/casa/util/casa_util/zebra_remote_client.c
(gdb) p client->ipv6_info_tree
$42 = (struct avl_table *) 0x3212c430
(gdb) p *client->ipv6_info_tree
$43 = {
avl_root = 0x321fc338,
avl_compare = 0x15196ec <ipv6_info_compare>,
avl_param = 0x0,
avl_alloc = 0x22e5250,
avl_count = 3343,
avl_generation = 12590,
free_node_list = 0x20,
free_node_cnt = 29
}
于是,往上溯源,在主线程里从zebra_client
查看
(gdb) p *zebra_client->ipv6_info_tree
$44 = {
avl_root = 0x321fc338,
avl_compare = 0x15196ec <ipv6_info_compare>,
avl_param = 0x0,
avl_alloc = 0x22e5250,
avl_count = 3343,
avl_generation = 12590
}
欸,少了两个字段
grep
一下源代码,发现里面确实有两种关于struct avl_table
的定义