代码之家  ›  专栏  ›  技术社区  ›  garrilla

C to非托管C++ DLL访问违规/“帧不在模块”

  •  1
  • garrilla  · 技术社区  · 6 年前

    我有一个C应用程序(在UnyDIS3D MUNO)中,它通过C API将一些数据传递给C++非托管DLL。它正在传入包含数组的嵌套结构。一切都很好,直到C-API关闭 } 当我从VS2017中收到“帧不在模块中”消息时,(如果我“>继续”,我将收到访问冲突 0xC0000005 反汇编建议可能缺少一个ptr-因此可能是一个取消引用错误)

    edit:我认为这可能是源结构有指向数组的指针//edit

    是什么导致了这个“框架不在模块中”?-作为一个信息,它不是很有信息性

    我该怎么办?

    我的密码…

    我有一个结构的C层次结构。

    private struct Vector3
    {
        public float x;
        public float y;
        public float z;
    }
    
    private structure Location
    {
        public Vector3 coords;
        public float distanceFromOrigin;
    }
    
    private struct Locations
    {
        [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 10)]
        public Location[] locations;
    }
    
    private struct Scene
    {
        public Locations cam1;
        public Locations cam2;
        public float timeInMilliSecs;
    }
    

    我正在实例化 Scene cam1 cam2 每个都得到一个数组 位置。一切都很好。按预期工作到现在,数据结构中填充了正确的数据。

    我通过了 场景 到非托管dll

    [DllImport(dllname)]
    private static extern void updateScene(Scene scene);
    

    在我的C++中

    extern "C" {
        DLL_EXPORT void updateScene(Scene scene);
    }
    

    过载

    void updateScene(Scene scene) {
        setSecene(scene); // this calls function fine but with erroneous data
    }
    

    和等价结构的签名

    struct Vector3
    {
        float x;
        float y;
        float z;
    }
    
    struct Location
    {
        Vector3 coords;
        float distanceFromOrigin;
    }
    
    struct Locations
    {
        Location locations[10];
    }
    
    struct Scene
    {
        Locations cam1;
        Locations cam2;
        float timeInMilliSecs;
    }
    

    这个 场景 结构被传递到 C 使用正确的数据,AN进入C++。但问题出现了——我猜这是一个记忆问题,但我不知道该怎么办。

    查看反汇编可能表明这是一个指针问题?

    0000000040BDAE57 49 89 0B mov qword ptr [r11],rcx

    有人能帮忙吗?

    2 回复  |  直到 6 年前
        1
  •  0
  •   shingo    6 年前

    上次你说你不改变 CallingConvention ,因此将值更改为 Cdecl .

    的默认值 DllImportAttribute WinApi 它不会在函数调用后清除堆栈。

    C代码的默认值为 __cdecl 也不能清除堆栈。它等待呼叫者清除它。

    发生了异常。

        2
  •  0
  •   garrilla    6 年前

    最后,我在一个指针中整理了整个嵌套结构-C中的所有更改#

    [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
    private static extern void updateScene(IntPtr scene);
    

    然后,在调用updateSecene()之前,我正在整理场景结构

    IntPtr  scenePtr = Marshal.AllocHGlobal(Marshal.SizeOf(scene));
    Marshal.StructureToPtr(scene, scenePtr , true);
    updateScene(scenePtr);
    

    其他一切都保持不变。