nm命令可以列出乙個函式庫檔案中的符號表。它對於靜態的函式庫和共享的函式庫都起作用。對於乙個給定的函式庫,nm命令可以列出函式庫中定義的所有符號,包括每個符號的值和型別。還可以給出在原程式中這個函式(符號)是在多少行定義的,不過這必須要求編譯該函式庫的時候加「-l」選項。
關於符號的型別,這裡我們再多討論一下。符號的型別是以乙個字母的形式顯示的,小寫字母表示這個符號是本地(local)的,而大寫字母則表示這個符號是全域性的(global,externel)。一般來說,型別有一下幾種:t、d、b、u、w。各自的含義如下:t表示在**段中定義的一般變數符號;d表示時初始化過的資料段;b表示初始化的資料段;u表示沒有定義的,在這個庫裡面使用了,但是在其他庫中定義的符號;w,weak的縮寫,表示如果其他函式庫中也有對這個符號的定義,則其他符號的定義可以覆蓋這個定義。
如果你知道乙個函式的名字,但是你不知道這個函式在什麼庫中定義的,那麼可以用mn的「-o」選項和grep命令來查詢庫的名字。-o選項使得顯示的每一行都有這個函式庫檔名。例如,你要查詢「cos」這個是在什麼地方定義的,大致可以用下面的命令:
nm libuserdecorate.so -a -l 2> /dev/null |grep init_cnf
libuserdecorate.so:0002e476 t _zn3zbp18userdecorateserver8init_cnfepkc /data/home/macky/svn/isd_qqvipserver_rep/decorate_proj/trunk/operate_server/src/main/user_decorate_server.cpp:76
關於nm的更詳細的用法:man nm
轉同事steven的一篇故障定位文章:
上線通知存在兩個問題:
1, 共享記憶體洩漏
2, 共享記憶體attach後沒有dettach。上線通知對共享記憶體的使用比較特殊,會在各個函式中呼叫attach以使用共享記憶體。這樣,在每次使用後沒有dettach的後果是:shm的nattach數量不斷遞增,到一定程度導致程式core。這個問題查了好久也沒有查出原因,之前在析構函式中加printf,發現根本沒有呼叫析構函式。在打算修改共享記憶體的使用方法時(共享記憶體只在啟動時attach,避免在功能函式中attach),still大師幫忙找出問題的關鍵所在。
下面分別談談這兩個問題的分析與定位。
1, 共享記憶體洩漏定位
ø 在出問題的機器上檢視共享記憶體使用情況,用ipcs
–m檢視結果存在大量如下共享記憶體段:
------ shared memory segments --------
key shmid owner perms bytes nattch status
0x00000000 1835059 user_00
600
204800
0
0x00000000 1867828 user_00
600 200
shm的key為0,大小固定。
ø 在開發機上啟動程式時統計大小為204800的共享記憶體塊的個數。
ipcs -m|grep 204800|wc –l
,發現每啟動一次,個數增加1.
ø 檢視上線通知程序id
ø 檢視各個程序的共享記憶體使用情況:
為便於顯示,省略時間戳資訊。
1) c
ache_main程序:
2) n
otify_worker程序id為11639)
主角出現,該worker使用了大小為204800的shm塊,並且key為0.
3) w
eihu_worker(程序id為11637)
發現只用到了乙個16m的shm,為worker與proxy之間的shm。
ø 結論:
notify_worker程序每次啟動時都會建立一塊shm大小為204800的共享記憶體塊。到初始化函式中檢查,並無對應的建立過程;後來比對與以前版本的區別發現之前版本有對應的建立過程,這個是由於自己注釋掉之後沒有立即重新編譯,後來忘記了這事:(
以後使用共享記憶體要多注意檢查!!!
2, 共享記憶體attach後沒有dettach,導致core。
首先,檢視程序中析構函式的彙編碼。執行gdb cache_main
disassemble main
,出現很多資訊,找到如下關注資訊:
反彙編cshmqueue,如下:
繼續反彙編~cshmqueue,如下:
發現該函式為空函式,按照**邏輯來說該函式應該去析構其成員cshm和csem物件,從而dettach共享記憶體。
進而推測該函式在鏈結成共享記憶體時被替換。
寫乙個簡單的指令碼對所有的靜態庫進行反彙編並利用cshmqueue過濾結果,發現
libcredence2.a
中有如下顯示:
發現該~cshmqueue為t,強型別函式。
再看看我們自身的析構函式,使用
nm -c cnotitysvr.o |grep cshmqueue
檢視如下:
發現該~cshmqueue為w,弱型別函式,因為我們的析構函式是內聯函式。
也可以檢視更詳細資訊如下,確定這個析構函式是我們自身的:
注意:如果在cshmqueue實現的靜態庫中用nm是查不到內聯析構函式的,只有在使用這個類的目標檔案中可以查到。
最後,確定我們的~cshmqueue是被
libcredence2.a
中同名析構函式覆蓋,之所以編譯時候沒有警告或者錯誤提示,是因為我們的析構函式是內聯函式。
解決方法:
ø 使用命名空間對類的作用域進行限制。
ø 以後類實現時,建構函式和析構函式盡量放在原始檔中,或者用特定的名字空間進行限制。
延伸閱讀(庫文件的開發與使用)http://www.cppblog.com/amazon/archive/2010/01/12/105471.html
C C Lib庫檔案nm除錯之符號表
本文主要介紹了一下在linux下開發c c 時候,不可避免的會開發或者生成.o a so這種中間庫狀態的檔案 可能是自己寫了乙個lib讓別人呼叫,或者提供.c cpp檔案嵌入別人的makefile工程 如何檢視這些庫檔案的一些基本資訊。有時候大家編譯程式時候 確切的說是鏈結器鏈結的時候 很多錯誤例如...
Mac平台下使用nm命令檢視檔案的符號表
在mac平台下,可以使用nm命令來檢視乙個檔案的符號表資訊。nm命令列工具是附帶在xcode中的,因此在使用之前請事先安裝好xcode。nm命令的格式大致如下 nm agnoprumxjlfpa s segname sectname t format arch arch flag file 如果不帶...
檢視 o, obj檔案符號列表,強大的nm命令
nm命令可以檢視,linux以及windows下的.o obj檔案中的符號列表,其中.o檔案可以由gcc,g 編譯得到,obj由vc編譯得到。太爽了。以後遇到undefined reference錯誤的時候就可以這個命令搞定了。舉一例子,在下面的原始碼中呼叫了乙個myprint函式 include ...