Меня интересует правильный способ выделения памяти для указателя (стиль C / C ++) изнутри C #.Затем, удерживая эту память в течение длительного периода времени.Кроме того, эта выделенная память предназначена для использования для вызовов DeviceIoControl ().Рассмотрим этот класс:
class Example {
const uint memCommit = 0x1000;
const uint pgReadWrite = 0x04;
[DllImport("Kernel32.dll", SetLastError = true)]
public static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, uint flAllocationType, uint flProtect);
[StructLayout(LayoutKind.Sequential)]
struct AStruct {
uint val1;
uint val2;
uint val3;
}
private static unsafe AStruct* pStruct = (AStruct*)VirtualAlloc(IntPtr.Zero, (UIntPtr)(sizeof(AStruct)), memCommit, pgReadWrite).ToPointer();
public static unsafe void ReadFromDevice() {
// setup the structure for the IOCTL call
pStruct->val1 = 70; //
pStruct->val2 = 0;
pStruct->val3 = 0x0f;
// call P/Invoked DeviceIoControl() here with pStruct as both the in/out pointers
// check that all is well
}
}
Все это мне не «кажется» правильным, но за эти годы я выучил достаточно, чтобы не сразу ставить под сомнение реализацию, не изучая ее.Вот что приводит меня на этот форум.Я вижу поведение, которого никогда не видел прежде.
Используя отладчик, я помещаю точку останова в точку, указатель которой создается при вызове VirtualAlloc ().Я запоминаю адрес, который мне дали (например, 0x03bf78cc).У меня также есть точка останова, размещенная в другой функции, которая вызывает метод ReadFromDevice () выше.Проходя через ReadFromDevice (), я замечаю, что pStruct содержит адрес, отличный от того, который был выделен при первом запуске программы.Значение pStruct изменилось с моего числа выше до, скажем, 0x03cd9004.
Я работал с вызовом функции Kernel32 DeviceIoControl () и раньше, и метод, который использовался там, был для создания закрепленного GCHandle дляСтруктура данных, используемая в вызове DeviceIoControl (), выполняет вызов, копирует соответствующие данные и освобождает дескриптор.Этот подход кажется менее подверженным ошибкам и согласуется с моделью распределения и освобождения неуправляемой памяти как можно быстрее.
Как я уже упоминал, подход, используемый в коде, которым я сейчас занимаюсь, просто не имеет "чувствую "правильно, но я не уверен, почему.Я ничего не нашел при поиске в Google таких вещей, как «c резкий адрес памяти изменился после alloc» и так далее.Следует ли изменить этот подход?(В прошлом я использовал закрепленные ручки GC.) Озвучен ли вышеуказанный подход?Независимо от того, почему указатель говорит один адрес памяти во время запуска программы, а затем другой, когда фактически выполняется вызов ReadFromDevice ()?Когда я пишу этот пост, мне интересно, является ли изменение адреса таким же «странным», как я сначала подумал.Тем не менее, я все еще подвергаю сомнению это использование указателей.Пожалуйста, сообщите.
Спасибо, Энди