Есть ли утечка unmanaged памяти?
От: adontz Грузия http://adontz.wordpress.com/
Дата: 24.09.10 23:28
Оценка:
Есть структура с полем — указателем на строку

[StructLayout(LayoutKind.Sequential)]
internal struct StringStruct
{
    [MarshalAs(UnmanagedType.LPWStr)]
    public string Text;
}

Нужно передать массив таких структур в unmanaged код. Делается это примерно так
int elementSize = Marshal.SizeOf(typeof(StringStruct));
IntPtr pointer = Marshal.AllocHGlobal(elementSize * this._elements.Length);

for (int index = 0; index < this._elements.Length; index++)
{
    Marshal.StructureToPtr(
        new StringStruct()
        {
            Text = this._elements[index]
        },
        new IntPtr(pointer.ToInt64() + elementSize * index),
        false);
}

Очевидно что под поля Text выделяются отдельные блоки памяти, так как в unmanaged представлении Text это просто структура.

Насколькоя понимаю, исполнив
Marshal.FreeHGlobal(pointer)

я эти блоки памяти не освобожу.

Что происходит на самом деле и как правильно освободить память? Может быть стооить исполнить
for (int index = 0; index < this._elements.Length; index++)
{
    Marshal.StructureToPtr(
        new StringStruct()
        {
            Text = null
        },
        new IntPtr(pointer.ToInt64() + elementSize * index),
        true);
}

?
A journey of a thousand miles must begin with a single step © Lau Tsu
Re: Есть ли утечка unmanaged памяти?
От: Pavel Dvorkin Россия  
Дата: 25.09.10 08:09
Оценка: +1
Здравствуйте, adontz, Вы писали:

Все далее — только мое ИМХО.

A>Есть структура с полем — указателем на строку


A>
A>[StructLayout(LayoutKind.Sequential)]
A>internal struct StringStruct
A>{
A>    [MarshalAs(UnmanagedType.LPWStr)]
A>    public string Text;
A>}
A>


Нет тут указателя на строку. Есть string — управляемый тип. На стороне С#. А маршаллинг пусть его на другой стороне представляет как указатель.

A>Нужно передать массив таких структур в unmanaged код. Делается это примерно так

A>
A>int elementSize = Marshal.SizeOf(typeof(StringStruct));
A>IntPtr pointer = Marshal.AllocHGlobal(elementSize * this._elements.Length);

Вот здесь выделили память под массив структур.

A>for (int index = 0; index < this._elements.Length; index++)
A>{
A>    Marshal.StructureToPtr(
A>        new StringStruct()
A>        {
A>            Text = this._elements[index]
A>        },
A>        new IntPtr(pointer.ToInt64() + elementSize * index),
A>        false);
A>}
A>

A>Очевидно что под поля Text выделяются отдельные блоки памяти, так как в unmanaged представлении Text это просто структура.

Нет структуры в unmanaged представлении. Есть new StringStruct управляемая, а в ней Text тоже управляемый.

A>Насколькоя понимаю, исполнив

A>
A>Marshal.FreeHGlobal(pointer)
A>


Вот тут ты память освободил.

A>я эти блоки памяти не освобожу.


А их и нет.

Резюме -за исключением Marshal.AllocHGlobal никакой неуправляемой памяти ты не просил, и освобождать тебе нечего. C помощью new из C# неуправляемую память ты не получишь.
With best regards
Pavel Dvorkin
Re[2]: Есть ли утечка unmanaged памяти?
От: adontz Грузия http://adontz.wordpress.com/
Дата: 25.09.10 11:14
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Резюме -за исключением Marshal.AllocHGlobal никакой неуправляемой памяти ты не просил, и освобождать тебе нечего. C помощью new из C# неуправляемую память ты не получишь.


Да, но маршалер-то выделяет память!
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[3]: Есть ли утечка unmanaged памяти?
От: Pavel Dvorkin Россия  
Дата: 25.09.10 11:32
Оценка: 39 (1)
Здравствуйте, adontz, Вы писали:

A>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>Резюме -за исключением Marshal.AllocHGlobal никакой неуправляемой памяти ты не просил, и освобождать тебе нечего. C помощью new из C# неуправляемую память ты не получишь.


A>Да, но маршалер-то выделяет память!


Да, верно.

Suppose your unmanaged block of memory is pointed to by ptr. The layout of this block is described by a corresponding managed class, structure. StructureToPtr marshals field values from a structure to a pointer. Suppose the ptr block includes a reference field, pointing to a string buffer currently holding "abc". Suppose the corresponding field on the managed side is a string holding "vwxyz". If you do not tell it otherwise, StructureToPtr allocates a new unmanaged buffer to hold "vwxyz", and hooks it up to the ptr block. This action casts the old buffer "abc" adrift without freeing it back to the unmanaged heap. You end up with an orphan buffer that represents a memory leak in your code. If you set the fDeleteOld parameter true, StructureToPtr frees the buffer holding "abc" before going on to allocate a new buffer for "vwxyz".

Но

public static void StructureToPtr(
Object structure,
IntPtr ptr,
bool fDeleteOld
)

fDeleteOld
Type: System.Boolean

true to have the Marshal.DestroyStructure method called on the ptr parameter before this method executes. Note that passing false can lead to a memory leak.

То есть можно передать true для очистки предыдущего выделенного блока. Этого, конечно, недостаточно — кто будет удалять последний раз. А вот Marshal.DestroyStructure и будет, если ты ее вызовешь.

Marshal.DestroyStructure Method

static void DestroyStructure(
IntPtr ptr,
Type^ structuretype
)

You can use this method to free reference-type fields, such as strings, of an unmanaged structure. Unlike its fields, a structure can be a value type or reference type. Value-type structures containing value-type fields (all blittable) have no references whose memory must be freed. StructureToPtr uses this method to prevent memory leaks when reusing memory occupied by a structure.
With best regards
Pavel Dvorkin
Re[4]: Есть ли утечка unmanaged памяти?
От: adontz Грузия http://adontz.wordpress.com/
Дата: 25.09.10 17:59
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Marshal.DestroyStructure Method


Вот его-то я и искал!
A journey of a thousand miles must begin with a single step © Lau Tsu
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.