向外部非托管方法传递字节[]或内存流时发生AccessViolationException

本文关键字:内存 AccessViolationException 字节 外部 方法 | 更新日期: 2023-09-27 18:01:06

我在托管Windows应用程序(Win.XP,.Net 3.5(中使用SlimDX。SlimDX处理所有未经管理的DirectX API调用。我正在尝试调用在SlimDX框架中找到的以下方法:SlimDX。Direct3D9.XFile.CreateEnumerationObject(流(。以下是实现:

XFile xfile = new XFile();
XFileEnumerationObject enumObj = null;
string Filename = @"MyDocs'Test.x";
using (FileStream fs = new FileStream(Filename, FileMode.Open, FileAccess.Read))
{
    enumObj = xfile.CreateEnumerationObject(fs);
}

当我调用这个方法时,我得到以下异常:

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at SlimDX.Direct3D9.XFile.CreateEnumerationObject(Byte[] memory)
   at SlimDX.Direct3D9.XFile.CreateEnumerationObject(Stream stream)
   at SceneGenerator.ContentManager.XParser.Parse(XParserMode Mode, MeshFlags options, List`1& materialPartitions, GDEAssetConfig& cfg, _XData& userContext, Byte[] filedata) in D:'Documents and Settings'GDEAuxiliary'My Documents'Visual Studio 2010'Projects'SceneGenerator'SceneGenerator'XParser.cs:line 191

SlimDX将处理此内存流到字节数组以及字节数组到非托管内存的转换。我想文件数据没有以预期的文本编码加载。。。

我已经使用SlimDX框架中的另一种方法验证了该文件,该方法使用文件名和指定的字符集创建枚举对象。。。这里是实现:

XFile xfile = new XFile();
XFileEnumerationObject enumObj = null;
string Filename = @"MyDocs'Test.x";
enumObj = xfile.CreateEnumerationObject(cfg.Filename, System.Runtime.InteropServices.CharSet.Auto);

这种方法效果很好。。。

我能做些什么来准备SlimDX的内存流。。。不幸的是,我不完全确定SlimDX对内存流的期望是什么。。。

向外部非托管方法传递字节[]或内存流时发生AccessViolationException

我去过那里。我不得不使用c#应用程序中的HBA API。无论我做什么,传递字节数组都会产生类似的错误。

对我有效的解决方案是将Byte[]数组封装在一个struct中,然后对该struct进行pasing。请确保将结构中的字节数组定义为Marshal。ByValArray,让c知道它的大小和一切。

根据我的经验,经验法则是当把东西传递到非托管内存时,确保你已经为它分配了托管内存

此外,我相信你已经检查过了,但请确保你的FileStream对象是有效的,它可以访问文件,文件不是空的。

以下是结构的示例:

    /*
    typedef struct HBA_wwn {
    HBA_UINT8 wwn[8];
    } HBA_WWN, *PHBA_WWN;
    */
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct HBA_WWN
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public Byte[] wwn;
        public static HBA_WWN getInstance()
        {
            HBA_WWN wwn = new HBA_WWN();
            wwn.wwn = new Byte[8];
            return wwn;
        }
    }