В нашем проекте мы связываем два приложения, одно на C #, а другое на C ++, по именованным каналам.Мы намерены передавать указатели памяти между ними и иметь возможность доступа к объектам, указанным ими в любом приложении.Наш текущий код вызывает исключение System.AccessViolationException:
System.AccessViolationException: Попытка чтения или записи в защищенную память.Это часто указывает на то, что другая память повреждена.
Пока что мы используем shared_ptr, который указывает на пользовательскую структуру и записывает указатель на буфер в C ++, как показано ниже:
typedef struct {
int one;
int a;
int two;
int b;
} DATA_STRUCT; // C++ struct
DATA_STRUCT ds;
ds.one = 10;
ds.a = 5;
ds.two = 99;
ds.b = 0;
shared_ptr<DATA_STRUCT> ptr_ds(new DATA_STRUCT);
shared_ptr<DATA_STRUCT> p(ptr_ds);
*ptr_ds = ds;
const int size = BUFFER_SIZE;
char buf[size];
memset(buf, 0xCC, 100);
while (keepReading)
{
printf("Write message:");
scanf("%s", buf);
memcpy(buf, &p, sizeof(shared_ptr<DATA_STRUCT>));
if (strcmp(buf, "quit") == 0)
keepReading = false;
else
{
WriteFile(hPipe1, buf, dwBytesToWrite, &cbWritten, NULL);
memset(buf, 0xCC, 100);
}
}
Затем в C # мы читаем весь буфер, сохраняем байты с соответствующей информацией в другом буфере (Rc) и преобразуем массив байтов в наши пользовательские данные.структура использует небезопасный IntPtr, как вы можете видеть ниже:
buffer = new byte[BUFFER_SIZE];
bytesRead = clientCSharp.stream.Read(buffer, 0, BUFFER_SIZE);
public struct DATA_STRUCT
{
public int one;
public int a;
public int two;
public int b;
}; // C# struct
unsafe
{
Buffer.BlockCopy(buffer, 0, Rc, 0, ReadLength);
DATA_STRUCT ds = new DATA_STRUCT();
IntPtr aux_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
IntPtr final_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
Marshal.Copy(Rc, 0, aux_ptr, 4);
final_ptr = (IntPtr)Marshal.PtrToStructure(aux_ptr, typeof(IntPtr));
ds = (DATA_STRUCT)Marshal.PtrToStructure(final_ptr, typeof(IntPtr));
}
Исключение возникает, когда мы пытаемся получить доступ к final_ptr для загрузки DATA_STRUCT, последнейстрока кода представлена выше.Здесь я приведу несколько изображений отладки:
C ++ Отладочный образ с Значение указателя, записанное в буфер именованного канала
C # Отладочный образ с Значение указателя, прочитанное из названного каналатруба уменьшенный буфер (Rc)
Может ли это быть что-то, связанное с длиной указателя?Как мне кажется, в приложении C ++ оно имеет 8 байтов, а в приложении C # - 16 байтов?Должны ли мы объявить безопасное место в памяти для C # и C ++?Если да, то как это можно сделать?
Примечание: Наша цель - работать с небезопасным IntPtr в приложении C #.В этом примере мы загружаем объект DATA_STRUCT, потому что мы хотели быть уверены, что в приложении C # мы извлекаем тот же объект, переданный в приложении C ++.Окончательные приложения предназначены для использования в Windows.