ienumerable とその内容を削除するためのきちんとした小さな関数を作成しました (最近発見したメモリ リークをプラグインするため):
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]
正直なところ、列挙可能なものを削除しても、中に含まれているオブジェクトを削除する必要があるかどうかはあまり心配していません。私たちはこれらのリストをいたるところで使用しており、リストが十分に迅速にクリーンアップされていなかったため、システムのメモリが不足していました。
さらに悪いことに、リスト追跡参照を nullptr に設定する関数に依存していましたDeleteEnumerable
が、それらが返されたときに追跡参照が更新されたようには見えません。コンソール出力からわかるように、デバッガーの問題だけではありません。
私が理解していないのは、なぜ