У меня есть класс (см. Пример ниже) , который действует как оболочка .NET для структуры памяти CUDA,
выделяется с помощью cudaMalloc () и ссылается с помощью поля члена типа IntPtr.
(Класс использует DllImport нативной C-библиотеки DLL, которая включает в себя различные функции CUDA.)
Методы dispose проверяют, является ли указатель IntPtr.Zero и, если нет, вызывает cudaFree ()
который успешно освобождает память (возвращает CUDA success)
и устанавливает указатель на IntPtr.Zero.
Метод finalize вызывает метод dispose.
Проблема состоит в том, что если методы finalize вызываются без вызова dispose, вызываемого ранее,
затем функция cudaFree () устанавливает код ошибки «недопустимый указатель устройства».
Я проверил, и адрес, который получает cudaFree (), совпадает с адресом, возвращаемым cudaMalloc (), и никакой dispose () не был вызван ранее.
Когда я добавляю вызов explict для dispose (), тот же адрес успешно освобождается.
Единственный найденный мной обходной путь - не вызывать метод dispose из финализатора, однако это может привести к утечке памяти, если dispose () вызывается не всегда.
Есть идеи, почему это происходит? - Я столкнулся с той же проблемой с CUDA 2.2 и 2.3, в .NET 3.5 SP1 в Windows Vista 64bit + GeForce 8800 и в Windows XP 32bit + Quadro FX (не знаю, какое число).
class CudaEntity : IDisposable
{
private IntPtr dataPointer;
public CudaEntity()
{
// Calls cudaMalloc() via DllImport,
// receives error code and throws expection if not 0
// assigns value to this.dataPointer
}
public Dispose()
{
if (this.dataPointer != IntPtr.Zero)
{
// Calls cudaFree() via DllImport,
// receives error code and throws expection if not 0
this.dataPointer = IntPtr.Zero;
}
}
~CudaEntity()
{
Dispose();
}
}
{
// this code works
var myEntity = new CudaEntity();
myEntity.Dispose();
}
{
// This code cause a "invalid device pointer"
// error on finalizer's call to cudaFree()
var myEntity = new CudaEntity();
}