“尝试读取或写入受保护的内存。这通常表明其他内存已损坏。导入C# [英] "Attempted to read or write protected memory. This is often an indication that other memory is corrupt" DllImporting C#

查看:1369
本文介绍了“尝试读取或写入受保护的内存。这通常表明其他内存已损坏。导入C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试将数据封送至我的DLL函数并返回C#代码时,出现了这个奇怪的错误。我看不到我在哪里传递null或读取无效的内存,并且此错误非常模糊。有任何线索吗?

I am getting this weird error while trying to marshal data to my DLL function and back to the C# code. I don't see where I am passing null or reading invalid memory and this error is so vague. Any clues??

以下代码:

FeeCalculation函数在DLL中的导出如下:

The FeeCalculation function is exported as follows in the DLL:

extern "C" __declspec(dllexport) void __stdcall FeeCalculation(char *cin, 
char *cout, char *flimit, char *frate,
char *fwindow, char *fincrement, char *fbird,
char *fparameter, char *fvalidation, char *fcoupon);

[StructLayout(LayoutKind.Sequential)]
        public struct feeAnswer
        {
            public uint fee;
            public uint tax1;
            public uint tax2;
            public uint tax3;
            public uint tax4;
            public uint surcharge1;
            public uint surcharge2;
            public uint validationFee;
            public uint couponFee1;
            public uint couponFee2;
            public uint couponFee3;
            public uint couponFee4;
            public ushort dstay;
            public ushort mstay;
        };

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct feeRequest
        {
            public byte day;
            public byte month;
            public uint year;
            public byte hour;
            public byte minute;
            public byte rate;
            public byte validation;
            public byte coupon1;
            public byte coupon2;
            public byte coupon3;
            public byte coupon4;
        };

        [DllImport("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
           CharSet = CharSet.Ansi)]
        public static extern void FeeCalculation(feeRequest cin,
            out feeAnswer cout, string flimit,
            string frate, string fwindow, string fincrement, string fbird,
            string fparameter, 
            string fvalidation, string fcoupon);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            feeRequest freq = new feeRequest();
            feeAnswer fans = new feeAnswer();

            string flim = "";
            string frat = "";
            string fwin = "";
            string finc = "";
            string fbir = "";
            string fpar = "";
            string fval = "";
            string fcoup = "";

            freq.day = 26;

            freq.month = 2;

            freq.year = 2010;   //2000 ~ 2099

            freq.hour = 20;

            freq.minute = 47;

            freq.rate = 15;

            freq.validation = 1;

            freq.coupon1 = 2;

            freq.coupon2 = 3;

            freq.coupon3 = 4;

            freq.coupon4 = 5;


            FeeCalculation(freq, out fans, flim, frat, fwin, finc, fbir, fpar, fval, fcoup);

根据约翰的建议:

public static extern void FeeCalculation(feeRequest cin,
            out feeAnswer cout, 
            [MarshalAs(UnmanagedType.LPArray)]
            IntPtr flimit,
           [MarshalAs(UnmanagedType.LPArray)]
            IntPtr frate,
           [MarshalAs(UnmanagedType.LPArray)]
            IntPtr fwindow,
           [MarshalAs(UnmanagedType.LPArray)]
            IntPtr fincrement,
           [MarshalAs(UnmanagedType.LPArray)]
            IntPtr fbird,
           [MarshalAs(UnmanagedType.LPArray)]
            IntPtr fparameter,
           [MarshalAs(UnmanagedType.LPArray)]
            IntPtr fvalidation,
           [MarshalAs(UnmanagedType.LPArray)]
            IntPtr fcoupon);

...

FeeCalculation(freq, out fans, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);


推荐答案

要解决此问题,我添加了在.DLL中的 memmove()代码周围。然后,我必须确保在所有参数上都使用 ref 关键字,因为否则内存地址将无法正确地引用到DLL。一旦执行完此操作,它现在就可以正常工作了,而且没有访问冲突。我不需要MarshalAs声明或任何pack语句。我只是能够使用 LayoutKind.Sequential

To fix it, I added a try / catch block around the memmove() code in the .DLL. Then, I had to make sure I was using the ref keyword on all parameters because otherwise the memory addresses were not being referred properly to the DLL. Once I did that, it works now with no access violation. I did not need the MarshalAs declarations nor any pack statements. I simply was able to use LayoutKind.Sequential.

这篇关于“尝试读取或写入受保护的内存。这通常表明其他内存已损坏。导入C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆