1

私たちの 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 プラットフォーム固有のマーシャリングの問題がいくつかあるという予感がありますが、その理由と場所を突き止めるのに苦労しています。

4

0 に答える 0