unsafe and GC

T

Tony Johansson

Hello!

I have read in a book that garbage collector(GC) is allowed to (and needs)
to move objects
in order to defragment the heap.

One thing that I wonder is what happen with those objects that I still have
a reference to and is using ?

This statement will not compile(in unsafe section)
int* pa = new int[5];
in a program because of the following that I don't understand
"What would happen if the garbage collector decide to move the object and we
were pointing to it and using it"
When having these kind of statement
int* pa = new int[5];
You I have to use a fixed keyword like this
(fixed) {int* pa = new int[5];}

I can't understand why the keyword fixed need to be used ?
I mean I don't use pointer but I use object that is located on the heap all
the time and those object is moved around by the GC and that works fine. So
why is it nesessary to use this keywork fixed when having statement like
this
int* pa = new int[5];

//Tony
 
T

Tony Johansson

rossum said:
Hello!

I have read in a book that garbage collector(GC) is allowed to (and needs)
to move objects in order to defragment the heap. Correct.


One thing that I wonder is what happen with those objects that I still
have
a reference to and is using ?
GC keeps all the references up to date as it moves stuff around.
This statement will not compile(in unsafe section)
int* pa = new int[5];
in a program because of the following that I don't understand
"What would happen if the garbage collector decide to move the object and
we
were pointing to it and using it"
The GC can update references, it cannot update pointers. Hence you
have to tell the GC not to move any object that you have a pointer to
so the GC knows to leave it in place.
When having these kind of statement
int* pa = new int[5];
You I have to use a fixed keyword like this
(fixed) {int* pa = new int[5];}
The fixed statement tells the GC that the object in question is not to
be moved because you are using a pointer to access it.
I can't understand why the keyword fixed need to be used ?
I mean I don't use pointer but I use object that is located on the heap
all
the time and those object is moved around by the GC and that works fine.
So
why is it nesessary to use this keywork fixed when having statement like
this
int* pa = new int[5];
Because you are using a pointer and not a reference. When moving
objects on the heap the GC can update references, it cannot update
pointers.

Reference:

int[] pa = new int[5];

Pointer

unsafe {
fixed (int* pa = new int[5]);
}

rossum

Well you mentioned that this was Reference:
That is wrong it's just 5 ints in an array stored by value
int[] pa = new int[5];

//Tony
 
T

Tony Johansson

Hello!

You say that
If you are simply
trying to allocate an array of 6 integers, use "int pa[5];"
That is wrong int pa[5] stores 5 int not 6 as you say
in index 0 to 4

//Tony


Michael Ober said:
What language are you using? Your code looks like it's C or C++, not C#.
Basically, although C# allows pointers, you must tell the GC that you are
using a pointer. The (fixed) clause is how to do that. If you are simply
trying to allocate an array of 6 integers, use "int pa[5];"

Mike.

Tony Johansson said:
Hello!

I have read in a book that garbage collector(GC) is allowed to (and
needs) to move objects
in order to defragment the heap.

One thing that I wonder is what happen with those objects that I still
have a reference to and is using ?

This statement will not compile(in unsafe section)
int* pa = new int[5];
in a program because of the following that I don't understand
"What would happen if the garbage collector decide to move the object and
we were pointing to it and using it"
When having these kind of statement
int* pa = new int[5];
You I have to use a fixed keyword like this
(fixed) {int* pa = new int[5];}

I can't understand why the keyword fixed need to be used ?
I mean I don't use pointer but I use object that is located on the heap
all the time and those object is moved around by the GC and that works
fine. So why is it nesessary to use this keywork fixed when having
statement like this
int* pa = new int[5];

//Tony
 
P

Peter Duniho

Tony said:
[...]
Because you are using a pointer and not a reference. When moving
objects on the heap the GC can update references, it cannot update
pointers.

Reference:

int[] pa = new int[5];

Pointer

unsafe {
fixed (int* pa = new int[5]);
}

rossum

Well you mentioned that this was Reference:
That is wrong it's just 5 ints in an array stored by value
int[] pa = new int[5];

The array _is_ a reference. The 5 ints have to be stored somewhere.
They are stored in the process's heap, within the array object that is
itself stored in the process's heap, as a reference type object.

Rossum's reply was correct. You can only use the "fixed" keyword to
convert reference types in the first place. The code wouldn't even
compile if the object wasn't a reference type.

Instead of telling Rossum that he's wrong (which is itself an incorrect
statement), explain that you don't yet understand the issue well enough
to see why he's right.

Note, by the way, one thing that Rossum's reply implies but didn't
specifically point out: any fixed object you have in the heap can (and
will) prevent the heap from being completely defragmented when the GC
wants to defragment it. Fragmentation in the heap is a problem for a
variety of reasons, but one of the most important is that it can prevent
future allocations from succeeding even though the total available
memory exceeds the needs of the allocation.

While you can use "fixed" to convert references to pointers, it is very
important to do so only in very limited situations, and only for very
limited periods of time.

Pete
 
T

Tony Johansson

Peter Duniho said:
Tony said:
[...]
Because you are using a pointer and not a reference. When moving
objects on the heap the GC can update references, it cannot update
pointers.

Reference:

int[] pa = new int[5];

Pointer

unsafe {
fixed (int* pa = new int[5]);
}

rossum

//Tony

Well you mentioned that this was Reference:
That is wrong it's just 5 ints in an array stored by value
int[] pa = new int[5];

The array _is_ a reference. The 5 ints have to be stored somewhere. They
are stored in the process's heap, within the array object that is itself
stored in the process's heap, as a reference type object.

Rossum's reply was correct. You can only use the "fixed" keyword to
convert reference types in the first place. The code wouldn't even
compile if the object wasn't a reference type.

Instead of telling Rossum that he's wrong (which is itself an incorrect
statement), explain that you don't yet understand the issue well enough to
see why he's right.

Note, by the way, one thing that Rossum's reply implies but didn't
specifically point out: any fixed object you have in the heap can (and
will) prevent the heap from being completely defragmented when the GC
wants to defragment it. Fragmentation in the heap is a problem for a
variety of reasons, but one of the most important is that it can prevent
future allocations from succeeding even though the total available memory
exceeds the needs of the allocation.

While you can use "fixed" to convert references to pointers, it is very
important to do so only in very limited situations, and only for very
limited periods of time.

Pete

I do know that an array is a reference type and that is stored in the heap
but I thought that he meant that the stored ints
was reference type. It was just some information that was added to what he
said.

//Tony
 
K

kndg

Hello!

I have read in a book that garbage collector(GC) is allowed to (and needs)
to move objects
in order to defragment the heap.

One thing that I wonder is what happen with those objects that I still have
a reference to and is using ?

This statement will not compile(in unsafe section)
int* pa = new int[5];
in a program because of the following that I don't understand
"What would happen if the garbage collector decide to move the object and we
were pointing to it and using it"
When having these kind of statement
int* pa = new int[5];
You I have to use a fixed keyword like this
(fixed) {int* pa = new int[5];}

I can't understand why the keyword fixed need to be used ?
I mean I don't use pointer but I use object that is located on the heap all
the time and those object is moved around by the GC and that works fine. So
why is it nesessary to use this keywork fixed when having statement like
this
int* pa = new int[5];

//Tony

Hi Tony,

Just would like to add to what others has said...
Array is a reference type and is allocated on the heap which is managed
by the GC, but you can allocate it on the stack by using the
"stackalloc" keyword and since it is allocated on the stack, you don't
have to use the "fixed" keyword. See below example,

public static unsafe void Main(string[] args)
{
const int MAX_SIZE = 5;
int* pa = stackalloc int[5];
int* pb = pa;

for (int i = 0; i < MAX_SIZE; i++, pa++)
{
*pa = i;
}

// show the value
pa = pb;

for (int i = 0; i < MAX_SIZE; i++, pa++)
{
Console.WriteLine(*pa);
}
}

Regards.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top