[lua] mac上如何编译snapshot(检测Lua中的内存泄露)

  最近我们的unity手游频繁闪退,只要进入战斗场景,之后一段时间就会闪退,如果是在unity编辑器中则会报出not enough memory的错误!猜测应该是有内存泄漏;

  由于我们使用了tolua,大部分业务逻辑都是在lua中编写的,这时要查出具体是哪里导致内存泄漏的很麻烦,我自己负责的模块有信心不会造成此类问题,所以单靠查看别人不规范的代码来排查感觉鸭梨山大,所以这时就想到云风的“一个 Lua 内存泄露检查工具“这篇博客里说的snapshot 来排查究竟是哪些地方导致的!因为我刚开始用mac电脑,压根就不知道怎么在mac os x上编译c访问lua。

  下载上面说的snapshot工具解压之后,mac上用终端cd到该目录下,用云风写的make macosx命令,但这时提示:

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000; background-color: #ffffff }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #34bc26; background-color: #ffffff }
span.s1 { }
span.s2 { color: #c33720 }

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命令如下:

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000; background-color: #ffffff }
span.s1 { }

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.dSYMsnapshot.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.将错误地址输入工具的文本框中,点击分析。

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000; background-color: #ffffff }
span.s1 { }

上一篇:JavaScript作用域和闭包


下一篇:在Mac OS X中配置Apache + PHP + MySQL