Уж извините за глупый вопрос, перечитываю тут Рихтера там такой код
internal static class FixedStatement
{
unsafe public static void Go()
{
// Allocate a bunch of objects that immediately become garbage
for (Int32 x = 0; x < 10000; x++) new Object();
IntPtr originalMemoryAddress;
Byte[] bytes = new Byte[1000]; // Allocate this array after the garbage object
// Get the address in memory of the Byte[]
fixed (Byte* pbytes = bytes) { originalMemoryAddress = (IntPtr)pbytes; }
// Force a collection; the garbage objects will go away & the Byte[] might be compacted
GC.Collect();
GC.WaitForPendingFinalizers();
// Get the address in memory of the Byte[] now & compare it to the first address
fixed (Byte* pbytes = bytes)
{
Console.WriteLine("The Byte[] did{0} move during the GC",
(originalMemoryAddress == (IntPtr)pbytes) ? " not" : null);
}
}
}
и текст из книги
Using C#’s fixed statement is more efficient that allocating a pinned GC handle. What happens
is that the C# compiler emits a special “pinned” flag on the pbytes local variable. During a garbage
collection, the GC examines the contents of this root, and if the root is not null, it knows not to
move the object referred to by the variable during the compaction phase. The C# compiler emits IL to
initialize the pbytes local variable to the address of the object at the start of a fixed block, and the
compiler emits an IL instruction to set the pbytes local variable back to null at the end of the fixed
block so that the variable doesn’t refer to any object, allowing the object to move when the next
garbage collection occurs.
Ведь переменная фиксируется и не перемещается при сборке только внутри fixed блока.
что то как то пример кажется не совсем актуален что ли, может интереснее было бы так:
internal static class FixedStatement
{
unsafe public static void Go()
{
// Allocate a bunch of objects that immediately become garbage
for (Int32 x = 0; x < 1000000; x++) new Object();
IntPtr originalMemoryAddress;
Byte[] bytes = new Byte[1000]; // Allocate this array after the garbage object
// Get the address in memory of the Byte[]
fixed (Byte* pbytes = bytes) {
originalMemoryAddress = (IntPtr)pbytes; //}
// Force a collection; the garbage objects will go away & the Byte[] might be compacted
GC.Collect();
GC.WaitForPendingFinalizers();
// Get the address in memory of the Byte[] now & compare it to the first address
//fixed (Byte* pbytes = bytes)
//{
Console.WriteLine("The Byte[] did{0} move during the GC",
(originalMemoryAddress == (IntPtr)pbytes) ? " not" : null);
}
}
}
[/cs]
Здравствуйте, Iso12, Вы писали:
I>Здравствуйте, HomoHabilis, Вы писали:
I>В этом примере как раз наглядно показано, что может произойти если не корректно использовать fixed блок и IntPtr.
I>По моему очень хороший пример.
просто я сам засомневался что понимаю правильно, поэтому и спросил здесь
т.е. первый пример — неправильное использование fixed
второй — правильное, так?
и еще момент хз может от размера памяти зависит бюджет нулевого поколения но на моей машине этого
// Allocate a bunch of objects that immediately become garbage
for (Int32 x = 0; x < 10000; x++) new Object();
мало что бы сборка запустилась(ну т.е. удалился бы мусор и живые объекты скомпоновались бы)
надо как минимум два нуля приписать
Здравствуйте, HomoHabilis, Вы писали:
HH>просто я сам засомневался что понимаю правильно, поэтому и спросил здесь
HH>т.е. первый пример — неправильное использование fixed
HH>второй — правильное, так?
Всё зависит от контекста, в котором этот пример приведён. Если это "Автоматическое управление памятью", то тут наглядно показаны процессы, которые происходят при работе GC и этот пример идеально подходит для этого.
HH>и еще момент хз может от размера памяти зависит бюджет нулевого поколения но на моей машине этого
HH>HH>// Allocate a bunch of objects that immediately become garbage
HH> for (Int32 x = 0; x < 10000; x++) new Object();
HH>
HH>мало что бы сборка запустилась(ну т.е. удалился бы мусор и живые объекты скомпоновались бы)
HH>надо как минимум два нуля приписать
На сколько я понимаю, сборка мусора должна произойти в любом случае при прямом вызове GC, оптимизация зависит от состояния памяти (могу и ошибаться).