请用写一段代码,让unity无声无息的崩溃。
你说这怕是有点难哦,谁会这么不幸呢?不幸的是,我幸运的成为了那个不幸的人。
unity里面调用dll的方式是使用 DllImport
,比如有一个 Hello.dll,里面有一个 char* Greet(char* name)
的方法。将 Hello.dll 放入Unity的Plugins目录下,如果没有就自己建一个,然后通过下面的代码导入dll。
[DllImport("Hello.dll")]
private extern static IntPtr Greet(byte[] name);
也可以通过 EntryPoint
来指定函数入口。
[DllImport("Hello.dll", EntryPoint = "Greet")]
嗯,一切正常。
刚开始确实很正常,直到后来有一次升级了dll,替换了部分依赖的dll,然后就GG了,dll返回的内存和预想不同,某些字节顺序被打乱了。
WTF??不是说编程没有玄学吗?
刚开始我们认为是dll本身的问题,但是经过测试发现dll本身没有问题,直接通过C#或者python调用dll,返回的内存都是正确的。这可就见鬼了,难道只有unity有问题?终究还是unity抗下了所有。
但有个奇怪的地方,只有在编辑器里运行有问题,打包出来运行也没问题。经过缜密的思考,反复实验,我们猜测是debug库release库的问题,也就是说编辑模式下得使用debug库才行。经过实验,果然如此,换成debug版本的dll,在编辑模式下也能得到正确的结果。
于是我们踩出第一个坑,某些dll在unity编辑模式下调用不正确,得换成debug版本的dll。注意,并不是所有的dll都会如此,而且大部分dll都不必如此,只有我们手动编译的FreeImage库出现了这个问题。
满心欢喜以为问题完美解决,可惜还是太年轻,福兮祸所伏,没想到还是个连环坑。使用debug库之后,调用dll时,unity直接崩溃,而且是悄无声息的,就这么退出了,不带走一片云彩。
观察 C:\Users\用户名\AppData\Local\Unity\Editor
下的 Editor.log,可以看到unity编辑器退出之前的日志。文件中记录了dll调用之后的日志,这也就是说调用dll本身并没有出错。
经过单步调试,发现是崩溃在释放内存的地方。
在VS中按F5启动调试,回到unity编辑器选择同意调试即可单步调试unity脚本。
IntPtr data = Greet(...);
Marshal.FreeHGlobal(data);
在编辑模式下,调用 Marshal.FreeHGlobal
释放dll分配的内存就会异常退出,当然,打包出来运行是正常的。
FreeHGlobal
的文档链接:点击跳转。
debug模式的dll该如何释放内存,目前还没有解决,但是如果不释放,确实会导致内存占用上涨,但好歹在编辑模式下,暂且放过它吧。果然程序都是靠bug运行的。