C# AcessExceptionViolation with Marshal.Copy
本文关键字:Copy Marshal with AcessExceptionViolation | 更新日期: 2023-09-27 18:01:34
我正在翻译一个程序从VB到c#,它与外部程序mmty . exe通信。这个程序有VB6.0的ActiveX控件,我在Visual Studio 2013中添加到我的c#项目。
在VB中的代码如下:
Dim m_nmmr(63) As Long
Private Sub XMMR_OnNotifyNMMR(pNMMR As Long)
Call CopyMemory(m_nmmr(0), pNMMR, 64 * 4) 'Windows API CopyMemory()*
当mmty . exe有数据并且pNMMR指向的数据被复制到m_nmmr(63)缓冲区时产生此事件。
我用c#编写的程序是这样的:[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
static extern void CopyMemory(Int32[] Destination, IntPtr Source, uint Length);
private void XMMR_OnNotifyNMMR(object sender, AxXMMTLib._DXMMREvents_OnNotifyNMMREvent e)
{
IntPtr ptr = (IntPtr)e.pNMMR;
Int32[] m_nmmr = new Int32[63];
Marshal.Copy(ptr, m_nmmr, 0, 63);
}*
但是当我执行它时,我得到一个AccessViolationException。它告诉我有人试图在受保护的内存中进行写或读操作。
我该如何解决这个问题?任何想法?
这是VB6.0原始方法的帮助:
void onnotifyynmmr (long* pNMMR)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~此事件在txm_level消息到达时生成。由pNMMR指向的NMMR结构体定义为
#pragma pack(push, 1)
typedef struct {
DWORD m_markfreq;
DWORD m_spacefreq;
DWORD m_siglevel;
DWORD m_sqlevel;
DWORD m_codeswitch;
DWORD m_codeview;
DWORD m_notch1;
DWORD m_notch2;
DWORD m_baud;
DWORD m_fig;
DWORD m_radiofreq;
DWORD m_Reserved[53];
}NMMR;
#pragma pack(pop)
如果应用程序使用此结构,则不必响应所有XMMR事件。由于NMMR结构体仅由LONG变量组成,因此可以将其复制到VB的LONG数组中。在xml .ocx中,数组的索引有几个名称,例如xr_markfreq。有关详细信息,请参阅XMMR的预定义常量。
[Example]
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Dim m_nmmr(63) As Long
Private Sub XMMR_OnNotifyNMMR(pNMMR As Long)
Call CopyMemory(m_nmmr(0), pNMMR, 64 * 4) 'Windows API CopyMemory()
|
MarkFreq = m_nmmr(xr_markfreq)
SpaceFreq = m_nmmr(xr_spacefreq)
|
'Pass pNMMR to the control for the supplemental control
Call XMMSpec.UpdateByNMMR(pNMMR) 'Update the frequency property of XMMSpec control
Call XMMLvl.DrawByNMMR(pNMMR) 'Draw the level indicator
End Sub
63是个问题:
在VB6中,63是顶部索引(0..63)。
在c#中,63是元素(0..62)的COUNT。
所以你错过了4个字节。你可以用一个小的控制台程序来检查,断点在第一次赋值时:
static void Main(string[] args)
{
int[] test = new int[1];
test[0] = 1;
test[1] = 2; // <- this will crash
}