c # взаимодействие сортировки и утилизации
-
05-07-2019 - |
Вопрос
У меня есть DLL, разработанная на C ++, включенная в проект на C #, и у меня есть странные исключения AccessViolationException, происходящие нерационально. Я подозреваю, что мой мусор неправильно собран. У меня есть неуправляемый метод apiGetSettings (из DLL), который должен копировать данные в объект настроек (на самом деле это структура в исходном коде, но .NET InterOp позволяет импортировать данные только как объекты класса. Я использую System.Runtime.InteropServices. Маршал использует методы для выделения и освобождения памяти, но это может оставить мусор, который разрушает все.
Теперь я должен реализовать методы IDisposable в классе Settings (это неуправляемо?). Если да, как я могу избавиться от строк, маршализованных как UnmanagedType.ByValTStr, и как я могу избавиться от объектов настроек?
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
class Settings
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 33)]
internal string d;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
internal string t;
internal int b;
}
[DllImport(".\\foobar.dll", EntryPoint = "getSettings")]
private static extern int apiGetSettings(IntPtr pointerToSettings);
void GetSettings(ref Settings settings)
{
int debug = 0;
// Initialize a pointer for the structure and allocate memory
IntPtr pointerToSettings = Marshal.AllocHGlobal(43);
// Connect the pointer to the structure
Marshal.StructureToPtr(settings, pointerToSettings, true);
// Point the pointer
debug = apiGetSettings(pointerToSettings);
// Copy the pointed data to the structure
Marshal.PtrToStructure(pointerToSettings, settings);
// Free the allocated memory
Marshal.FreeHGlobal(pointerToSettings);
}
Решение
Нет, вам не нужно реализовывать IDisposable. Ваш класс настроек является управляемым классом (эти атрибуты предназначены только для целей выполнения) и будет собирать мусор.
Мое первое предположение: вы выделяете 43 байта, но обе ваши строки добавляют до 70 байтов (помните, если вы не используете древнюю Win98 / Me, размер одного символа составляет 2 байта), так что вы ' не выделяет достаточно. Вместо этого используйте Marshal.SizeOf для динамического определения размера структуры.