簡體   English   中英

C#AcessExceptionViolation與Marshal.Copy

[英]C# AcessExceptionViolation with Marshal.Copy

我正在將程序從VB轉換為與外部程序MMTTY.EXE通信的C#。 該程序具有適用於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()*

當MMTTY.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 OnNotifyNMMR(long * pNMMR)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~此事件在TXM_LEVLEL消息到達的時間生成。 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數組。 數組的索引在XMMT.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是元素的COUNT(0..62)。

因此,您會錯過4個字節。 您可以使用一個小的控制台程序在第一次分配時使用斷點來簡單地檢查它:

    static void Main(string[] args)
    {
        int[] test = new int[1];
        test[0] = 1;
        test[1] = 2; // <- this will crash
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM