最近我們的unity手游頻繁閃退,只要進入戰斗場景,之后一段時間就會閃退,如果是在unity編輯器中則會報出not enough memory的錯誤!猜測應該是有內存泄漏;
由於我們使用了tolua,大部分業務邏輯都是在lua中編寫的,這時要查出具體是哪里導致內存泄漏的很麻煩,我自己負責的模塊有信心不會造成此類問題,所以單靠查看別人不規范的代碼來排查感覺鴨梨山大,所以這時就想到雲風的“一個 Lua 內存泄露檢查工具“這篇博客里說的snapshot 來排查究竟是哪些地方導致的!因為我剛開始用mac電腦,壓根就不知道怎么在mac os x上編譯c訪問lua。
下載上面說的snapshot工具解壓之后,mac上用終端cd到該目錄下,用雲風寫的make macosx命令,但這時提示:
make macosx
gcc -g -Wall --shared -undefined dynamic_lookup -o snapshot.so snapshot.c
snapshot.c:1:10: fatal error: 'lua.h' file not found
#include <lua.h>
^
1 error generated.
make: *** [macosx] Error 1
很明顯是snapshot.c中引用#include <lua.h>找不到lua.h這個文件;這應該就是我的lua.h和lua庫沒有在指定的目錄下系統找不到的緣故。但我不懂在編譯過程中指定目錄,所以使用谷歌搜索了之后,找到了別人提的跟我一樣的問題的答案:https://github.com/lefcha/imapfilter/issues/84,原文如下:
This is a matter of telling the make utility and/or your compiler where to find the installed Lua include files and libraries. Imapfilter tries to find the Lua include files in /usr/local/include and the Lua libs at /usr/local/lib, but if they were installed somewhere else, it would fail just like in your case.
You can override the Makefile paths, by setting the INCDIRS and LIBDIRS variables, eg.
make INCDIRS=-I/path/to/lua/include LIBDIRS=-L/path/to/lua/lib
Where /path/to/lua/include is where your Lua include files reside, and /path/to/lua/lib is where your Lua libs are located.
也就是要使用命令NCDIRS=-I/path/to/lua/include LIBDIRS=-L/path/to/lua/lib 來告訴系統lua.h文件及lua庫在哪里!接着又參考了一下上面下載的lua-snapshot-master中的Makefile文件中的命令:
mingw51 :
gcc -g -Wall --shared -o snapshot.dll snapshot.c -I/usr/local/include -L/usr/local/bin -llua51
macosx :
gcc -g -Wall --shared -undefined dynamic_lookup -o snapshot.so snapshot.c
最后終結得出的編譯snapshot命令如下:
gcc -g -Wall --shared -undefined dynamic_lookup -o snapshot.so snapshot.c -I/usr/local/include -L/usr/local/lib
編譯成功,在lua-snapshot-master目錄下生成snapshot.so.dSYM和snapshot.so這兩個文件,然后我就直接用sublime打開lua-snapshot-master,接着運行dump.lua文件得到預期的輸出結果:
userdata: 0x7fee33603f50 table
0x7fee34000008 : tmp : /Users/alphaapple/Downloads/lua-snapshot-master/dump.lua:7
userdata: 0x7fee33606140 table
0x7fee34000008 : S1 : /Users/alphaapple/Downloads/lua-snapshot-master/dump.lua:7
[Finished in 0.0s]
另外,如果使用命令gcc -O2 -bundle -undefined dynamic_lookup -o snapshot.so snapshot.c -I/usr/local/include -L/usr/local/lib
則只生成snapshot.so文件,而不會生成snapshot.so.dSYM
題外話:.dSYM文件?它的作用?
下面轉載自:http://www.cocoachina.com/ios/20141219/10694.html
什么是 dSYM 文件
Xcode編譯項目后,我們會看到一個同名的 dSYM 文件,dSYM 是保存 16 進制函數地址映射信息的中轉文件,我們調試的 symbols 都會包含在這個文件中,並且每次編譯項目的時候都會生成一個新的 dSYM 文件,位於 /Users/<用戶名>/Library/Developer/Xcode/Archives 目錄下,對於每一個發布版本我們都很有必要保存對應的 Archives 文件 ( AUTOMATICALLY SAVE THE DSYM FILES 這篇文章介紹了通過腳本每次編譯后都自動保存 dSYM 文件)。
dSYM 文件有什么作用
當我們軟件 release 模式打包或上線后,不會像我們在 Xcode 中那樣直觀的看到用崩潰的錯誤,這個時候我們就需要分析 crash report 文件了,iOS 設備中會有日志文件保存我們每個應用出錯的函數內存地址,通過 Xcode 的 Organizer 可以將 iOS 設備中的 DeviceLog 導出成 crash 文件,這個時候我們就可以通過出錯的函數地址去查詢 dSYM 文件中程序對應的函數名和文件名。大前提是我們需要有軟件版本對應的 dSYM 文件,這也是為什么我們很有必要保存每個發布版本的 Archives 文件了。
如何將文件一一對應
每一個 xx.app 和 xx.app.dSYM 文件都有對應的 UUID,crash 文件也有自己的 UUID,只要這三個文件的 UUID 一致,我們就可以通過他們解析出正確的錯誤函數信息了。
1.查看 xx.app 文件的 UUID,terminal 中輸入命令 :
dwarfdump --uuid xx.app/xx (xx代表你的項目名)
2.查看 xx.app.dSYM 文件的 UUID ,在 terminal 中輸入命令:
dwarfdump --uuid xx.app.dSYM
3.crash 文件內第一行 Incident Identifier 就是該 crash 文件的 UUID。
dSYM工具(下載地址:https://github.com/answer-huang/dSYMTools)
於是我抽了幾個小時的時間將這些命令封裝到一個應用中,也為以后解決bug提供了便利。
使用步驟:
1.將打包發布軟件時的xcarchive文件拖入軟件窗口內的任意位置(支持多個文件同時拖入,注意:文件名不要包含空格)
2.選中任意一個版本的xcarchive文件,右邊會列出該xcarchive文件支持的CPU類型,選中錯誤對應的CPU類型。
3.對比錯誤給出的UUID和工具界面中給出的UUID是否一致。
4.將錯誤地址輸入工具的文本框中,點擊分析。