Выделение указателя на массив указателей на структуру Исключение «невозможно чтение или запись в защищенную память» - PullRequest
0 голосов
/ 02 ноября 2019

Я перевожу нативную библиотеку C ++ в C #. Исходная функция выделяет некоторую память структуры, выполняя некоторые манипуляции с памятью текущего процесса и возвращая манипулированные байты в байтовый буфер внутри структуры.

Структура определяется следующим образом:

typedef struct tdMEM_SCATTER_HEADER {
    DWORD magic;            
    WORD version;           
    WORD Future1;
    ULONG64 qwA;            
    DWORD cbMax;            
    DWORD cb;               
    PBYTE pb;             
    PVOID pvReserved1;      
    PVOID pvReserved2;      
    PVOID Future2[8];
} MEM_SCATTER_HEADER, *PMEM_SCATTER_HEADER, **PPMEM_SCATTER_HEADER;

Исходная функция определяется следующим образом:

DWORD Scatter(_Inout_ PPMEM_SCATTER_HEADER ppMEMs, _In_ DWORD count);

, а последовательность выделения равна

pbBuffer = LocalAlloc(0, count * (sizeof(PMEM_SCATTER_HEADER) + sizeof(MEM_SCATTER_HEADER) + 0x1000));
ZeroMemory(pbBuffer, count * (sizeof(PMEM_SCATTER_HEADER) + sizeof(MEM_SCATTER_HEADER)));
for(i = 0; i < cMEMs; i++) {
     pMEM->pb = pbData + ((QWORD)i << 12); // Allocating return bytes buffer.
}

Вот что я попробовал:

Структурирование:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct MEM_SCATTER_HEADER
{
     public uint magic;            
     public ushort version;        
     public ushort Future1;
     public ulong qwA;            
     public uint cbMax;            
     public uint cb;                
     [MarshalAs(UnmanagedType.ByValArray)]
     public byte[] pb;             
     public IntPtr pvReserved1;     
     public IntPtr pvReserved2;                
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
     public IntPtr[] Future2;
}

Выделение памяти:

MEM_SCATTER_HEADER[] header = new MEM_SCATTER_HEADER[count];

for (int i = 0; i < count; i++)
{
     header[i].pb = new byte[0x1000];
     Array.Clear(header[i].pb, 0, header[i].pb.Length); // Fill array with 0
}

DLLImport:

[DllImport("testC.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern uint Scatter(ref MEM_SCATTER_HEADER ppMems, uint count);

И, наконец, вызов функции:

uint count = Scatter(ref header, count);

У меня было время отладки, неправильно ли я собираю данные, или мне нужно сделать несколько ручных сортировок, чтобы избавиться от исключения: «Попытка чтения или записи защищенной памяти. Это часто указывает на то, что другая память повреждена. "" При вызове функции.

1 Ответ

0 голосов
/ 03 ноября 2019

Первоначальное распределение не обнуляет всю выделяемую память и выглядит неправильно. Это как если бы код делал:

int bigchunk = sizeof(PMEM_SCATTER_HEADER) + sizeof(MEM_SCATTER_HEADER) + 0x1000;
int smallchunk = sizeof(PMEM_SCATTER_HEADER) + sizeof(MEM_SCATTER_HEADER);

pBuffer = LocalAlloc(0, count * bigchunk);
ZeroMemory(pBuffer, count * smallchunk);

Может быть, дело?

...