AIX应对编译链接问题的一些解决办法和思路

文章讨论的问题如题

某某模块里面有个函数
static void init_memory_debugging(void)

/*
  *  Description:  Opens a file for memory logging if:
  *               code compiled with MEMORY_DEBUG defined
  *               and environment variable MEMORY_DEBUG_ON is defined.
  *               Uses file name $MEMORY_DEBUG_FILE, defaulting to
  *               "memory.log".  If unable to open
  *               this, continues as if no memory debugging.
  */
从函数的描述可以看出,需要使用该函数,得define MEMORY_DEBUG. 我们就得把MEMORY_DEBUG这个编译选项加入到makefile里面去。接着就以为大功告成可以使用该函数了,立即敲入 ck -V /usr1/arbor/bin/BIP,结果@#¥%~~一大堆错误。

======== Rebuilding "bip_equip.o" ========
        xlC128_r -q64  -+ -D_AIX -D_REENTRANT -qrtti=dynamiccast -brtl -g  -DMODULE_BIP -DMEMORY_DEBUG -DNEW_TAX_GEO -I/usr1/arbor/src/billing/bip -I/usr1/arbor/src/include -I/usr1/arbor/bp_common_src/src -I/usr1/arbor/duct_src/duc_lib -I/usr1/arbor/oam_src/include -I/usr1/arbor/tax_src/include   -I/usr1/arbor/mps_src/libs/ths_sender -I/usr1/arbor/denver_src/billing/bill_lib/error -c bip_equip.c
"/usr/vacpp/include/xlocinfo", line 81.18: 1540-0274 (S) The name lookup for "debug_free" did not find a declaration.
"bip_proto.h", line 730.6: 1540-1298 (I) "void debug_free(void *, int, char *)" needs to be declared in the containing scope to be found by name lookup.
"/usr/vacpp/include/xlocinfo.t", line 38.50: 1540-0274 (S) The name lookup for "debug_free" did not find a declaration.
"bip_proto.h", line 730.6: 1540-1298 (I) "void debug_free(void *, int, char *)" needs to be declared in the containing scope to be found by name lookup.
"/usr/vacpp/include/xlocinfo.t", line 49.52: 1540-0274 (S) The name lookup for "debug_free" did not find a declaration.
"bip_proto.h", line 730.6: 1540-1298 (I) "void debug_free(void *, int, char *)" needs to be declared in the containing scope to be found by name lookup.
"/usr/vacpp/include/xlocale", line 731.25: 1540-0274 (S) The name lookup for "debug_free" did not find a declaration.
"bip_proto.h", line 730.6: 1540-1298 (I) "void debug_free(void *, int, char *)" needs to be declared in the containing scope to be found by name lookup.
"/usr/vacpp/include/xlocale", line 746.25: 1540-0274 (S) The name lookup for "debug_free" did not find a declaration.
"bip_proto.h", line 730.6: 1540-1298 (I) "void debug_free(void *, int, char *)" needs to be declared in the containing scope to be found by name lookup.
*** Error code 1
clearmake: Error: Build script failed for "bip_equip.o"

摘出错误的一段,The name lookup for "debug_free" did not find a declaration,这个编译错误大家都知道吧,没找到debug_free()的声明,奇怪的是该错误是AIX系统库文件里面报的错,而且debug_free()在bip_proto.h里面声明了的,这下懵了。顿了几分钟过后,想到这个是AIX的库文件的错误,该不会是系统不兼容init_memory_debugging函数吧,就立马跑到HPUX下,找个view,加上MEMORY_DEBUG 编译选项,ck -V ~arbor/bin/BIP,编过了!!!!这种系统不兼容的问题,对于我这个原生态菜鸟来说,感觉到很难很难。
再看一下第二句错误,needs to be declared in the containing scope to be found by name lookup,我看到这句话的第一印象是命名空间的问题,而且在google上有很多类似错误的解决办法,这下心里踏实多了,就尝试着加namespace XXX{},各种名称的namespace,各种循环嵌套的namespace,结果错误依旧是错误,而且一点都没变。

把google上类似错误的解决办法差不多都试了一下,还是不行,千奇百怪的错误。然后只能到代码里面去找找问题的原因了。
bip_encodes.h里面有段代码 #define free(p) debug_free((p), __LINE__, (char *)__FILE__) ,对库函数宏定义了一下,乍一看这语法没问题啊,我把这段代码改成 #define free(p) my_debug_free((p), __LINE__, (char *)__FILE__) ,结果报错是The name lookup for "my_debug_free" did not find a declaration,又冥思了十多分钟想到该不会是BIP调用到的AIX库文件用到了free这个函数吧。立马运行vi "/usr/vacpp/include/xlocinfo"(报错的第一句话),搜索free 发现一段代码,

   +73                  // CLASS _Timevec
   +74  class _Timevec {
   +75  public:
   +76          _Timevec(void *_P = 0)
   +77                  : _Ptr(_P) {}
   +78          _Timevec(const _Timevec& _Rhs)
   +79                  {*this = _Rhs; }
   +80          ~_Timevec()
   +81                  {free(_Ptr); }
   +82          _Timevec& operator=(const _Timevec& _Rhs)
   +83                  {_Ptr = _Rhs._Ptr;
   +84                  ((_Timevec *)&_Rhs)->_Ptr = 0;
   +85                  return (*this); }
   +86          void *_Getptr() const
   +87                  {return (_Ptr); }
   +88  private:
   +89          void *_Ptr;
   +90          };

错误终于找到了xlocinfo文件里面的_Timevec 类用到了free(),然后free会被替换成debug_free(),所以报错,这也能很好的解释我把#define free(p) debug_free((p), __LINE__, (char *)__FILE__) 换成
#define free(p) my_debug_free((p), __LINE__, (char *)__FILE__) 也报错的原因了,该怎么办呢?请教大神!

在展示大神的一些解决方法之前再次总结一下错误的根本原因: AIX库文件 xlocinfo里类_Timevec的析构函数用到了free,然后会被替换成debug_free。为什么会被替换成debug_free呢?因为BIP在包含xlocinfo这个文件之前已经包含了bip_encodes.h这个头文件了。那又为什么会报错 The name lookup for "debug_free" did not find a declaration,是因为在bip_equip.c里,声明debug_free的头文件bip_proto.h 是在包含xlocinfo 之后被包含的(此论点是通过分析bip_equip.c的编译信息得出,下面的内容将讨论如何获取编译bip_equip.c的信息)

解决问题的步骤:

1) 论证bip_equip.c里,声明debug_free的头文件bip_proto.h 是在包含xlocinfo 之后被包含的。
单独编译bip_equip.c,通过设置-E选项来获取编译bip_equip.c的信息。
xlC128_r -q64  -+ -D_AIX -D_REENTRANT -qrtti=dynamiccast -brtl -g  -DMODULE_BIP -DMEMORY_DEBUG -DNEW_TAX_GEO -I/usr1/arbor/src/billing/bip -I/usr1/arbor/src/include -I/usr1/arbor/bp_common_src/src -I/usr1/arbor/duct_src/duc_lib -I/usr1/arbor/oam_src/include -I/usr1/arbor/tax_src/include   -I/usr1/arbor/mps_src/libs/ths_sender -I/usr1/arbor/denver_src/billing/bill_lib/error -c bip_equip.c -E >! bip_equip.i
分析bip_equip.i可以看到,debug_free的声明是在20k line左右,而debug_free的调用都是在10K line 以前,所有有力的证明了我们的论点。

2)解决以上论点所得出的错误,可以将debug_free函数放到bip_equip.c的最上面再声明一次。再编,结果在编译bip_invoice.c的时候,同样的错误再次出现。呵呵,总算把bip_equip.c编过了。要编译过bip_invoice.c, 也是同样的方法,在bip_invoice.c的最上面 声明debug_free... 写到这,大家肯定会觉得很麻烦,万一接下来在其他.c文件里面又出现同样的错误(事实上的确如此),岂不是每一个文件都得添加声明语句,这样肯定会被认为是一个菜鸟写的代码。
    仔细观察BIP的C代码,你应该会有些收获,大多数 .c文件的第一句代码(不包含注释)是 #include "arbor_global.h",我们可以看到arbor_global.h被包含的优先级还挺高的哈,那就把debug_free(同理还有debug_malloc,debug_calloc,debug_realloc,因为如果不添加这三个函数的声明到arbor_global.h文件里面去的话,会有和debug_Free同样的编译错误)的声明放到arbor_global.h的最开始的地方吧。
    再编!终于编译通过了,但是又来了个链接错误。
   ld: 0711-317 ERROR: Undefined symbol: .debug_malloc
    *** Error code 8
clearmake: Error: Build script failed for "/usr1/arbor/bin/BIP"
不认识.debug_malloc这个链接符号,这下就该使用 -bloadmap选项来获取详细的链接信息了。
xlC128_r -q64  -+ -D_AIX -D_REENTRANT -qrtti=dynamiccast -brtl -brtl -bexpall bip_init.o  bip_account.o  bip_account_aux.o  bip_adj.o  bip_aggr_usage.o  bip_backout.o  bip_bacs.o  bip_balance.o  bip_base_cr.o  bip_bmf.o  bip_bonus_point.o  bip_ccard.o  bip_cmf.o  bip_contracts.o  bip_credit_note.o  bip_ctl_rpt.o  bip_currency.o  bip_descr.o  bip_discount.o  bip_equip.o  bip_equip_aux.o  bip_hist_contract.o  bip_icb_discounts.o  bip_invoice.o  bip_ipc.o  bip_late_fee.o  bip_lct.o  bip_nrc.o  bip_prepayment.o  bip_rc.o  bip_rc_discon.o  bip_rollback.o  bip_sec_equip.o    bip_unform.o  bip_usage.o  bip_util.o  bip_work_list.o  lct_crypt.o bip_bpc_interface.o  bip_duc_interface.o  bip_tax_interface.o arbor_version.o  -L/usr1/arbor/src/lib -L/usr1/arbor/site_specific/lib -L/usr1/arbor/3p/oracle/AIX/lib -L/usr/ccs/lib -L/usr/lib -L/usr/local/lib -lrc -lacct_balance -llate_fee -lmpstsender -lduc -lductmp -ltax -lgeo    -ltaxcommon -lbp_common -loam_bic_client -larbor_mod -loam_stdism_all -lismapi -lismutil -lC -loam_stdism_all -loam_stdism_forced_heartbeat -lprocess_work -larbor_thread -larbor_mod -larbor_init_thread -larbor_prov -loam_emit -larbor_mod -larbor_dbutils -larbor_oracle -larbor_utils  -larbor_mod -loam_stdism_all -lismapi -lismutil -lC -loam_stdism_all -loam_stdism_forced_heartbeat -lprocess_work  -lm   -larbor_ipc  -lpthread -larbor_thread -lclntsh  -lc -lm -lPW -lnsl /usr/lib/libintl.a -ltax -lgeo    -ltaxcommon -o /usr1/arbor/bin/BIP-bloadmap:filename

然后查看filename这个文件,直接跳到最后一行,会发现类似于
 .debug_malloc             [21483] ER PR bip_duc_interface.cpp(bip_duc_interface.o)
这样的错误。
使用nm来列出目标文件的符号清单。
nm -BC *.o|grep .debug_malloc
         - U .debug_malloc__FUliPc
         - U .debug_malloc__FUliPc
         - U .debug_malloc__FUliPc
         - U .debug_malloc__FUliPc
         - U .debug_malloc__FUliPc
         - U .debug_malloc__FUliPc
         - U .debug_malloc__FUliPc
         - U .debug_malloc__FUliPc
         - U .debug_malloc
         - U .debug_malloc__FUliPc
         - U .debug_malloc__FUliPc
         - U .debug_malloc__FUliPc
     16084 T .debug_malloc__FUliPc
     80856 d debug_malloc__FUliPc
     88808 D debug_malloc__FUliPc
         - U .debug_malloc__FUliPc
         - U .debug_malloc__FUliPc
         - U .debug_malloc__FUliPc
         - U .debug_malloc__FUliPc
         - U .debug_malloc__FUliPc
         - U .debug_malloc__FUliPc
         - U .debug_malloc__FUliPc
发现有个地方是用C而不是C++的方式去链接的,查看 bip_duc_interface.o
nm -BC bip_duc_interface.o|grep .debug_malloc 
- U .debug_malloc
发现就是bip_duc_interface.o链接的时候出现的错误,bip_duc_interface.o去链接.debug_malloc()这个函数是是以查询debug_malloc__FUliPc符号的方式去链接的,但是现在只有.debug_malloc这个符号,所以我们得用extern C来特别说明,我是C的方式来声明的,而不是C++!这样bip_duc_interface.o去链接.debug_malloc()这个函数就会去查询debug_malloc这个符号。我想大家都应该知道extern ”C“ 关键字吧,对于extern "C"可以理解成在C++/C中的混合编程的编译指令。 我们试着将 arbor_global.h里面声明这几个函数包裹上 extern "C"{}.

再编译一次试试。
看到了这句话,...BIP build complete...,终于~~~成功了。

在看一下所有object文件的debug_malloc符号
nm -BC *.o|grep .debug_malloc

         - U .debug_malloc
         - U .debug_malloc

         - U .debug_malloc
         - U .debug_malloc
         - U .debug_malloc
         - U .debug_malloc
         - U .debug_malloc
         - U .debug_malloc
         - U .debug_malloc
         - U .debug_malloc
         - U .debug_malloc
         - U .debug_malloc
     16076 T .debug_malloc
     80824 d debug_malloc
     88776 D debug_malloc
         - U .debug_malloc
         - U .debug_malloc
         - U .debug_malloc
         - U .debug_malloc
         - U .debug_malloc
         - U .debug_malloc
         - U .debug_malloc

全被指定为C的方式来声明的。

总结:
1)编译选项 -E,获取编译的详细信息。
2)链接选项 -bloadmap, 获取链接的具体信息。
3)  nm命令,用来列出目标文件的符号清单


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值