函数重名和结构体出现两种定义

发布时间 2023-09-25 14:44:42作者: 枝桠

这个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_treeipv4_neigh_treempls_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的定义