Я создал аккуратную маленькую функцию для удаления неисчислимого и его содержимого (чтобы устранить утечку памяти, которую я недавно обнаружил):
generic<typename T>
void CollectionHelpers::DeleteEnumerable(IEnumerable<T>^% enumerable)
{
if(enumerable != nullptr)
{
for each( T obj in enumerable)
{
delete obj;
}
delete enumerable;
enumerable = nullptr;
}
}
... но по какой-то причине, когда я прослеживаю с помощью отладчика, список все еще указывает на некоторую память, когда я возвращаюсь из функции DeleteEnumerable
.
Я думал, что, передавая в качестве ссылки отслеживания, он должен изменить дескриптор, который я передаю? Что я здесь пропустил?
Редактировать : более тщательный пример теста ...
Это немного обновленный диспозитор:
using namespace GenericCollections;
using namespace System::Collections::Generic;
using namespace System;
generic<typename T>
void CollectionHelpers::DeleteEnumerable(IEnumerable<T>^% enumerable)
{
if(enumerable != nullptr)
{
for each( T obj in enumerable )
{
Console::WriteLine("Disposing of object");
delete obj;
}
Console::WriteLine("Disposing of enumerable");
delete enumerable;
enumerable = nullptr;
}
if( enumerable == nullptr )
{
Console::WriteLine("enumerable tracking reference is nullptr");
}
else
{
Console::WriteLine("enumerable tracking reference is NOT nullptr");
}
}
Это сокращенный пример кода, который вызывает диспозитор:
using namespace System;
using namespace GenericCollections;
using namespace System::Collections::Generic;
ref class MyClass
{
private:
int* m_myBuf;
public:
MyClass()
{
m_myBuf = new int[100];
Console::WriteLine("MyClass::MyClass()");
}
~MyClass()
{
delete [] m_myBuf;
m_myBuf = NULL;
Console::WriteLine("MyClass::~MyClass()");
}
};
int main(array<System::String ^> ^args)
{
List<MyClass^>^ myList = gcnew List<MyClass^>;
myList->Add(gcnew MyClass());
myList->Add(gcnew MyClass());
myList->Add(gcnew MyClass());
CollectionHelpers::DeleteEnumerable(myList);
if(myList == nullptr)
{
Console::WriteLine("Original list is disposed of");
}
else
{
Console::WriteLine(String::Format("Original list still referenced: {0}", myList));
}
return 0;
}
... и это вывод:
MyClass::MyClass()
MyClass::MyClass()
MyClass::MyClass()
Disposing of object
MyClass::~MyClass()
Disposing of object
MyClass::~MyClass()
Disposing of object
MyClass::~MyClass()
Disposing of enumerable
enumerable tracking reference is nullptr
Original list still referenced: System.Collections.Generic.List`1[MyClass]
Если честно, меня не очень волнует, удаляют ли перечисленные работы объекты, содержащиеся внутри, которые должны были быть убиты. Мы используем эти списки повсеместно, и нашей системе не хватает памяти, потому что они не очищаются достаточно быстро.
Хуже того, мы полагались на функцию DeleteEnumerable
, чтобы установить для наших ссылок отслеживания списка значение nullptr, но когда они возвращаются обратно, ссылка отслеживания, похоже, не обновляется. Это не просто проблема отладчика, как вы можете видеть из вывода консоли.
Я не понимаю, почему