文章讨论的问题如题
某某模块里面有个函数
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命令,用来列出目标文件的符号清单