私たちの Unity3D ゲームは、フレームワークの一部に C++ DLL を使用しており、すべて Windows で正常に動作しています。最近、Linux 用のゲームをビルドしようとしたところ、かなりひどいハード クラッシュが発生しました。
問題を Unity3D 自体から切り離しました -> C++ ライブラリがなくても、Windows と Linux の間で問題なく動作します。
ライブラリを Ubuntu x64 環境内の Linux lib にコンパイルしました。
ゲームは最初のシーンに正常に読み込まれます (Unity3D が正常であることを証明します) が、ライブラリを利用するレベルを読み込むと、Unity3D から渡されたデータでライブラリ関数の 1 つを呼び出すときに、不良メモリでセグメンテーション違反が発生します。
ライブラリのデバッグ バージョンをコンパイルし、Linux の gdb でゲームを実行して、以下のデバッグ コール スタックを生成しました。
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff7fd3780 (LWP 7347)]
0x00007fffb42d94da in geom::Vector3f::Vector3f (this=0x1adff9a8, other=...)
at /mnt/hgfs/WFTO/war-for-the-overworld/CustomPlugins/GameLogic/GameLogic/Source/lib/geom/Vector3f.h:16
16/mnt/hgfs/WFTO/war-for-the-overworld/CustomPlugins/GameLogic/GameLogic/Source/lib/geom/Vector3f.h: No such file or directory.
(gdb)
Continuing.
Program received signal SIGABRT, Aborted.
0x00007ffff6236425 in raise () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) bt
#0 0x00007ffff6236425 in raise () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007ffff6239b8b in abort () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x00007ffff2749f6c in ?? () from /home/ryan/.gvfs/build on strich/Release/Linux/WFTO_Data/Mono/x86_64/libmono.so
#3 0x00007ffff27876e9 in ?? () from /home/ryan/.gvfs/build on strich/Release/Linux/WFTO_Data/Mono/x86_64/libmono.so
#4 <signal handler called>
#5 0x00007fffb42d94da in geom::Vector3f::Vector3f (this=0x1adff9a8, other=...)
at /mnt/hgfs/WFTO/war-for-the-overworld/CustomPlugins/GameLogic/GameLogic/Source/lib/geom/Vector3f.h:16
#6 0x00007fffb42db207 in data::LocatedObject::LocatedObject (this=0x1adff920, id=48, clientObject=0x23,
ownerPlayerNumber=0, location=...)
at /mnt/hgfs/WFTO/war-for-the-overworld/CustomPlugins/GameLogic/GameLogic/Source/components/data/abstract/LocatedObject.h:23
#7 0x00007fffb42db75e in data::PhysicalObject::PhysicalObject (this=0x1adff920, id=48, clientObject=0x23,
ownerPlayerNumber=0, location=..., bounds=..., orientation=..., collisionType=data::COLLISION_FULL_SOLID)
at /mnt/hgfs/WFTO/war-for-the-overworld/CustomPlugins/GameLogic/GameLogic/Source/components/data/abstract/PhysicalObject.h:40
#8 0x00007fffb42e443c in data::PropData::PropData (this=0x1adff920, id=48, clientObject=0x23, ownerPlayerNumber=0,
location=..., bounds=..., orientation=...)
at /mnt/hgfs/WFTO/war-for-the-overworld/CustomPlugins/GameLogic/GameLogic/Source/components/data/prop/PropData.h:18
#9 0x00007fffb42b6e0d in data_PropData_new (id=48, clientObject=0x23, ownerPlayerNumber=0,
location=<error reading variable: Cannot access memory at address 0x4208cccd429acccd>,
bounds=<error reading variable: Cannot access memory at address 0x3f666666>,
orientation=<error reading variable: Cannot access memory at address 0x1cb3>)
at /mnt/hgfs/WFTO/war-for-the-overworld/CustomPlugins/GameLogic/GameLogic/Source/components/data/prop/PropData_export.h:32
上記に基づいて、根本的な原因がどこにあるかは非常に明確です。data_PropData_newを呼び出すと、関数に渡されたいくつかのパラメータへの不正なメモリ ポインタがライブラリに取得されます。C++ 関数ヘッダーは次のとおりです。
extern "C" {
DLL_EXPORT PropData* data_PropData_new(
long long id, ManagedReference clientObject, int ownerPlayerNumber,
geom::Vector3f location, geom::Vector3f bounds, geom::Vector3f orientation)
C# DllImport:
[DllImport("GameLogic", EntryPoint = "data_PropData_new", CallingConvention = CallingConvention.Cdecl)]
internal static extern NativePropData create(
long id, IntPtr clientObject, int ownerPlayerNumber,
Vector3f location, Vector3f bounds, Vector3f orientation);
最初に気付くのは、不良メモリがタイプgeom::Vector3fのすべてのパラメーターにあることです。わかりました、それは良い手がかりです。以下は、C++ と C# の両方のVector3fコードです。
Vector3f.h (かなり大きいので PasteBin しました)。
Vector3f.cs (かなり大きいので PasteBin しました)。
このライブラリは Windows で問題なく動作することに注意してください。しかし、Linux ではありません。Linux で Vector3f データが適切にメモリに固定されていない可能性はありますか? Vector3f で Mono InteropServices プラットフォーム固有のマーシャリングの問題がいくつかあるという予感がありますが、その理由と場所を突き止めるのに苦労しています。