“尝试读取或写入受保护的内存。这通常表明其他内存已损坏。导入C# [英] "Attempted to read or write protected memory. This is often an indication that other memory is corrupt" DllImporting 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);
推荐答案
要解决此问题,我添加了 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屋!