By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,587 Members | 1,101 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,587 IT Pros & Developers. It's quick & easy.

int number = new int();

P: n/a
Hello!

If I write this statement
int number = new int();
I don't get compiler error or run time error
but how will the compiler read such a statement ?

For example will number be a reference to a new int on the heap?

//Tony

Sep 26 '08 #1
Share this Question
Share on Google+
28 Replies


P: n/a
Tony Johansson <jo*****************@telia.comwrote:
If I write this statement
int number = new int();
I don't get compiler error or run time error
but how will the compiler read such a statement ?

For example will number be a reference to a new int on the heap?
No. The above is the same as writing:

int number = 0;

"new" doesn't imply "create object on the heap" in C# - it just implies
"call the constructor". For value types, that doesn't create a new
object, it just initializes a new value.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Sep 26 '08 #2

P: n/a
Hi,

int is in C# a shortcut for Int32 (even in 64bits computers).

Int32 is a structure they never are placed on the heap.

Cor
Sep 26 '08 #3

P: n/a
On Sep 26, 11:58*am, "Cor Ligthert [MVP]" <notmyfirstn...@planet.nl>
wrote:
int is in C# a shortcut for Int32 (even in 64bits computers).
Correct.
Int32 is a structure they never are placed on the heap.
Well, they're on the heap:
1) If they're boxed
2) If they're part of another value which is on the heap

For instance:

class Foo
{
int x;
}

Here, any instance of Foo lives on the heap, including its x variable.

"Structs live on the stack" is a myth.
See http://pobox.com/~skeet/csharp/memory.html for more info.

Jon
Sep 26 '08 #4

P: n/a
Hello!

This is not really true:
Int32 is a structure they never are placed on the heap.
because of
If you box an int like.
int number = 1;
object o = number; // here number is still a value type of type Int32 but is
copied to heap when being boxed
// so o is stored on the stack and will
reference number which is stored on the heap.

//Tony
"Cor Ligthert [MVP]" <no************@planet.nlwrote in message
news:e2**************@TK2MSFTNGP05.phx.gbl...
Hi,

int is in C# a shortcut for Int32 (even in 64bits computers).

Int32 is a structure they never are placed on the heap.

Cor
Sep 26 '08 #5

P: n/a
On Sep 26, 1:55*pm, "Tony Johansson" <t.johans...@logica.comwrote:
This is not really true:Int32 is a structure they never are placed on the heap.

because of
If you box an int like.
int number = 1;
object o = number; // here number is still a value type of type Int32 but is
copied to heap when being boxed
* * * * * * * * * * * * * * * // so o is stored on the stack and will
reference number which is stored on the heap.
No, the variable "number" is still on the stack. The value of "o" is a
reference to a boxed copy of the value which number had at the time of
the assignment. If you change the value of number, that won't be seen
if you then look at o.

Jon
Sep 26 '08 #6

P: n/a
Hello!

Assume you have the following.
int number = 1;
object o = number;
If you here change the value of number it won't change what o is refering to
because that
is stored on the heap.
So we have one value of number which is stored on the stack and when we do
object o = number
a copy of this actual value number is put on the heap. f we now change
number by using this statement
number = 2;
the number that o is refering to is still 1;

I almost 99.99 % sure that this is correct.

//Tony

"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:76**********************************@e53g2000 hsa.googlegroups.com...
On Sep 26, 1:55 pm, "Tony Johansson" <t.johans...@logica.comwrote:
This is not really true:Int32 is a structure they never are placed on
the heap.

because of
If you box an int like.
int number = 1;
object o = number; // here number is still a value type of type Int32 but
is
copied to heap when being boxed
// so o is stored on the stack and will
reference number which is stored on the heap.
No, the variable "number" is still on the stack. The value of "o" is a
reference to a boxed copy of the value which number had at the time of
the assignment. If you change the value of number, that won't be seen
if you then look at o.

Jon

Sep 26 '08 #7

P: n/a
On Sep 26, 2:28*pm, "Tony Johansson" <t.johans...@logica.comwrote:
Assume you have the following.
int number = 1;
object o = number;
If you here change the value of number it won't change what o is referingto
because that is stored on the heap.
Yes.
So we have one value of number which is stored on the stack and when we do
object o = number
a copy of this actual value number is put on the heap.
Yes.
If we now change number by using this statement
number = 2;
the number that o is refering to is still 1;
Correct.
I almost 99.99 % sure that this is correct.
Absolutely. I was merely correcting this statement that you made
before:

// so o is stored on the stack and will
// reference number which is stored on the heap.

"o" doesn't reference "number". It reference an object which was
created with a value which happened to be the value of "number" at the
time. The two variables are independent immediately after the
assignment.

Jon
Sep 26 '08 #8

P: n/a
Hello!

I just wonder if it's then correct to say that
Int32 is a structure they never are placed on the heap.
I mean when you are boxing a copy is actually stored on the heap
as I described

//Tony
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:73**********************************@k30g2000 hse.googlegroups.com...
On Sep 26, 2:28 pm, "Tony Johansson" <t.johans...@logica.comwrote:
Assume you have the following.
int number = 1;
object o = number;
If you here change the value of number it won't change what o is refering
to
because that is stored on the heap.
Yes.
So we have one value of number which is stored on the stack and when we do
object o = number
a copy of this actual value number is put on the heap.
Yes.
If we now change number by using this statement
number = 2;
the number that o is refering to is still 1;
Correct.
I almost 99.99 % sure that this is correct.
Absolutely. I was merely correcting this statement that you made
before:

// so o is stored on the stack and will
// reference number which is stored on the heap.

"o" doesn't reference "number". It reference an object which was
created with a value which happened to be the value of "number" at the
time. The two variables are independent immediately after the
assignment.

Jon

Sep 26 '08 #9

P: n/a
On Sep 26, 3:15*pm, "Tony Johansson" <t.johans...@logica.comwrote:
I just wonder if it's then correct to say thatInt32 is a structure theynever are placed on the heap.

I mean when you are boxing a copy is actually stored on the heap
as I described
Indeed. It's also on the heap when it's part of another object. See my
response to Cor.

(Even a local variable can be on the heap if it's captured as part of
an iterator block or anonymous function...)

Jon
Sep 26 '08 #10

P: n/a
OD
Well, they're on the heap:
1) If they're boxed
2) If they're part of another value which is on the heap
that's just like an optical effect, it seems to be on the heap but
strictly speaking you can't say the int is on the heap in both cases
you're listing. It can be confusing for beginners.
In case 1) the value is transformed into an object and this object is
stored on the heap, initial value is not really on the heap.
In case 2) the value is localy stored in a structure (parent object's
memory area) that is on the heap, it is not really and directly on the
heap by itself.

It's a bit like saying an egg can fly... if you bring it with you in a
plane ! :-)

--
OD___
www.e-naxos.com
Sep 27 '08 #11

P: n/a
OD <OD <webmaster @ e-naxos dot com>wrote:
Well, they're on the heap:
1) If they're boxed
2) If they're part of another value which is on the heap

that's just like an optical effect, it seems to be on the heap but
strictly speaking you can't say the int is on the heap in both cases
you're listing.
The data which represents the integer lives somewhere in memory, right?
That memory is on the heap. Therefore the value is on the heap, to my
mind. It's certainly not on the stack.
It can be confusing for beginners.
In case 1) the value is transformed into an object and this object is
stored on the heap, initial value is not really on the heap.
No, but the value *in the box* is on the heap. The object contains the
same data (as a copy) as the original value.
In case 2) the value is localy stored in a structure (parent object's
memory area) that is on the heap, it is not really and directly on the
heap by itself.
I didn't say it was on the heap *by itself*. I said it was on the heap.
I believe that to be entirely accurate, and with appropriate
explanation (linked in the post) I don't think it confuses people.
Compare that with the "structs are on the stack, classes are on the
heap" myth: at that point there's a contradiction when you consider a
class containing a value type instance variable.
It's a bit like saying an egg can fly... if you bring it with you in a
plane ! :-)
No, it would be like saying an egg can be 10,000 feet above the ground
- which it certainly can if it's on a plane.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Sep 27 '08 #12

P: n/a
hi group,

is it really important to know if some object goes to the heap or to the
stack?

thanks, Carlos

"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:a3**********************************@c58g2000 hsc.googlegroups.com...
On Sep 26, 3:15 pm, "Tony Johansson" <t.johans...@logica.comwrote:
I just wonder if it's then correct to say thatInt32 is a structure they
never are placed on the heap.
>
I mean when you are boxing a copy is actually stored on the heap
as I described
Indeed. It's also on the heap when it's part of another object. See my
response to Cor.

(Even a local variable can be on the heap if it's captured as part of
an iterator block or anonymous function...)

Jon
Sep 28 '08 #13

P: n/a
On Sat, 27 Sep 2008 17:37:36 -0700, xcal <a@a.comwrote:
is it really important to know if some object goes to the heap or to the
stack?
It could be. Lifetime of an object is managed differently depending on
where it's stored. Inasmuch as one may need to correctly understand the
lifetime of an object, it's important to know where that object is stored.

More importantly, it's _always_ important to be accurate in one's
statements about behavior in a programming language. People should not
make untrue statements about a language, even if they believe that those
untrue statements have no practical relevance.

The question of whether an object is a reference type or a value type is
independent from the question of where the data for that object is
stored. Saying otherwise is incorrect.

Pete
Sep 28 '08 #14

P: n/a
xcal <a@a.comwrote:
is it really important to know if some object goes to the heap or to the
stack?
That's a very perceptive question. Arguably not, so long as the
CLR/framework/compiler hides the details in an efficient enough manner.

See http://csharpindepth.com/ViewNote.aspx?NoteID=41

However, it can occasionally be an interesting way of thinking about
other aspects of behaviour. It's easy enough to see that if data is to
be shared between threads, it has to be on the heap - and conversely,
that if data is only on the stack, it's threadsafe. (Assuming no
*really* nasty hacks, admittedly.)

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Sep 28 '08 #15

P: n/a
OD
Why can't you just say "ok, i was wrong" ?

--
OD___
www.e-naxos.com
Sep 28 '08 #16

P: n/a
OD <OD <webmaster @ e-naxos dot com>wrote:
Why can't you just say "ok, i was wrong" ?
Because I don't think I was. The "value types are on the stack;
reference types are on the heap" is a myth which confuses people. I try
to set the record straight. I've helped a number of people on this
matter. Why would I now say I was wrong, if I still don't believe I
was?

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Sep 28 '08 #17

P: n/a
Peter Duniho <Np*********@nnowslpianmk.comwrote:
That's not what I meant:

Action Method(ref int i)
{
return delegate { i = i + 1; };
}

That's not allowed, for good reason. That is, it prohibits the one
dangerous use case I can think of that might have led to access to stack
data for one thread from another.
Right. Not only is it dangerous in terms of multiple threads, but even
in a single thread I don't see how it could work.
Not sure what you meant, but the thread-safe aspect seems sensible to
me - if the data is on the stack, how can another thread get at it?

Note that the above example I'm talking about _can_ be easily implemented
using unsafe code, simply by passing a pointer instead of a by-ref
argument. The delegate returned could then be passed to a thread that
executes it and, vo?la, it's modifying data on a different thread's stack.
Yes - fortunately both sides would need to know about it (as described
below).
Unsafe code at both sides (I suspect) - which means it would at least
be deliberate.

I'm not sure what you mean by "both sides". It is possible for the code
managing the thread itself to be unaware of the access, but yes...the code
actually _doing_ the access (executed by the thread in the form of a
delegate) would necessarily need to be aware, because it would have to be
unsafe, as would the code providing access, because it also would have to
be usafe.
Exactly. Both the caller and the callee would need to be using unsafe
code, and explicitly handle the pointers. My point is that you're
unlikely to *accidentally* get into this situation.
[...]
So, what's _your_ definition of "*really* nasty hacks"? I assume it
includes the use of unsafe code. :)
Not necessarily - but anything which is deliberately making stack data
available to a different thread is really nasty (and brittle) IMO.

Well, the code passing the reference to the data may not know that the
data will be accessed on a different thread, while the code accessing the
data on a different thread may not know that the data came from the
stack. Both sides would have to be marked as unsafe, but there might not
be any deliberate intent to make stack data available to a different
thread (willfull ignorance would be more descriptive in that scenario :) ).
Mmm. I'm pleased that I can't easily *accidentally* let this kind of
thing happen.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Sep 28 '08 #18

P: n/a
hi Jon and Peter,

Thanks for your comments, these things are very complicated affairs.

Carlos.

"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP*********************@msnews.microsoft.com. ..
Peter Duniho <Np*********@nnowslpianmk.comwrote:
That's not what I meant:

Action Method(ref int i)
{
return delegate { i = i + 1; };
}

That's not allowed, for good reason. That is, it prohibits the one
dangerous use case I can think of that might have led to access to stack
data for one thread from another.

Right. Not only is it dangerous in terms of multiple threads, but even
in a single thread I don't see how it could work.
Not sure what you meant, but the thread-safe aspect seems sensible to
me - if the data is on the stack, how can another thread get at it?
Note that the above example I'm talking about _can_ be easily
implemented
using unsafe code, simply by passing a pointer instead of a by-ref
argument. The delegate returned could then be passed to a thread that
executes it and, vo?la, it's modifying data on a different thread's
stack.
>
Yes - fortunately both sides would need to know about it (as described
below).
Unsafe code at both sides (I suspect) - which means it would at least
be deliberate.
I'm not sure what you mean by "both sides". It is possible for the code
managing the thread itself to be unaware of the access, but yes...the
code
actually _doing_ the access (executed by the thread in the form of a
delegate) would necessarily need to be aware, because it would have to
be
unsafe, as would the code providing access, because it also would have
to
be usafe.

Exactly. Both the caller and the callee would need to be using unsafe
code, and explicitly handle the pointers. My point is that you're
unlikely to *accidentally* get into this situation.
[...]
>So, what's _your_ definition of "*really* nasty hacks"? I assume it
>includes the use of unsafe code. :)
>
Not necessarily - but anything which is deliberately making stack data
available to a different thread is really nasty (and brittle) IMO.
Well, the code passing the reference to the data may not know that the
data will be accessed on a different thread, while the code accessing
the
data on a different thread may not know that the data came from the
stack. Both sides would have to be marked as unsafe, but there might
not
be any deliberate intent to make stack data available to a different
thread (willfull ignorance would be more descriptive in that scenario
:) ).
>
Mmm. I'm pleased that I can't easily *accidentally* let this kind of
thing happen.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com

Sep 28 '08 #19

P: n/a
On Sun, 28 Sep 2008 11:25:58 -0700, Jon Skeet [C# MVP] <sk***@pobox.com>
wrote:
Peter Duniho <Np*********@nnowslpianmk.comwrote:
>That's not what I meant:

Action Method(ref int i)
{
return delegate { i = i + 1; };
}

That's not allowed, for good reason. That is, it prohibits the one
dangerous use case I can think of that might have led to access to stack
data for one thread from another.

Right. Not only is it dangerous in terms of multiple threads, but even
in a single thread I don't see how it could work.
Do you mean in theory? Or based on some specifics about how the CLR works?

To me, it's obvious in theory how it'd work. But I don't know enough
about the CLR to know whether it'd support that sort of thing. It may be
that in any language, you have to use pointers rather than references to
implement the behavior.
[...]
Exactly. Both the caller and the callee would need to be using unsafe
code, and explicitly handle the pointers. My point is that you're
unlikely to *accidentally* get into this situation.
Well, it seems to me that there's a broad gap between "accidently
implemented" and "nasty hack". That was the gist of my comment. I agree
it'd be a hack, but I've seen far nastier (probably been responsible for a
few over the years, for that matter...not that I'm proud of that :) ). I
was mostly just curious what your threshold for "nasty hack" is...sounds
like it's pretty low. :) (Not that there's anything wrong with that...to
each their own).

Pete
Sep 28 '08 #20

P: n/a
Jon Skeet [C# MVP] kirjoitti:
OD <OD <webmaster @ e-naxos dot com>wrote:
>Why can't you just say "ok, i was wrong" ?

Because I don't think I was. The "value types are on the stack;
reference types are on the heap" is a myth which confuses people. I try
to set the record straight. I've helped a number of people on this
matter. Why would I now say I was wrong, if I still don't believe I
was?
I think OD is right. When the program sees int, it is always a value
that comes from the stack. There is something on heap that is boxed or
inside a class, but the new int (like the original message asked) is
created onto stack.

--
Arto Viitanen
Sep 29 '08 #21

P: n/a
Peter Duniho <Np*********@nnowslpianmk.comwrote:
Right. Not only is it dangerous in terms of multiple threads, but even
in a single thread I don't see how it could work.

Do you mean in theory? Or based on some specifics about how the CLR works?

To me, it's obvious in theory how it'd work. But I don't know enough
about the CLR to know whether it'd support that sort of thing. It may be
that in any language, you have to use pointers rather than references to
implement the behavior.
Well, consider this program:

class Test
{
public static void Main()
{
Action foo = Foo();
foo();
}

public static Action Foo()
{
int i = 5;
return Bar(ref i);
}

public static Action Bar(ref int x)
{
return (Action) delegate()
{
x++;
Console.WriteLine(x);
}
}
}

What would you expect running that to do? I can't see how it can
compile and run without blowing up (or being unpredictable). The
variable x can't be captured in the normal way, because effectively the
variable itself is being passed in (rather than an initial value).
[...]
Exactly. Both the caller and the callee would need to be using unsafe
code, and explicitly handle the pointers. My point is that you're
unlikely to *accidentally* get into this situation.

Well, it seems to me that there's a broad gap between "accidently
implemented" and "nasty hack". That was the gist of my comment. I agree
it'd be a hack, but I've seen far nastier (probably been responsible for a
few over the years, for that matter...not that I'm proud of that :) ). I
was mostly just curious what your threshold for "nasty hack" is...sounds
like it's pretty low. :) (Not that there's anything wrong with that...to
each their own).
Well, anything involving pointers would make me suspicious to start
with - and anything relying on a particular stackframe in one thread
still being around by the time another thread executed some code just
sounds pretty evil to me.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Sep 29 '08 #22

P: n/a
On Sun, 28 Sep 2008 22:11:21 -0700, Arto Viitanen
<ar***********@microteam.fiwrote:
Jon Skeet [C# MVP] kirjoitti:
>OD <OD <webmaster @ e-naxos dot com>wrote:
>>Why can't you just say "ok, i was wrong" ?
Because I don't think I was. The "value types are on the stack;
reference types are on the heap" is a myth which confuses people. I try
to set the record straight. I've helped a number of people on this
matter. Why would I now say I was wrong, if I still don't believe I was?
I think OD is right.
That would be a mistake on your part.
When the program sees int, it is always a value
that comes from the stack.
That's simply not true. Nor do I believe that's what OD was writing.
There is something on heap that is boxed or
inside a class, but the new int (like the original message asked) is
created onto stack.
There's no such thing as a "new int". As in the original question, it's
simply a notation that represents the default value for the type. It
doesn't reside anywhere until it's copied to a variable, and where it
resides depends on the variable to which it's copied. It is _not_
"created onto stack" unless the destination is itself on the stack.

In particular, if the variable is part of a reference type (i.e. is a
member field), then the instance of the reference type is stored on the
heap, and the member field contained by that instance is as well. The
stack need never be involved.

Even in the original question, you cannot claim that the int is copied to
a stack variable, because the original poster didn't provide us with
enough detail to know where his "int number" is declared.

Even if you buy the person posting as "OD"'s claim that when a value type
is part of another value that's on the heap, it is "not really and
directly on the heap by itself" (a silly statement, IMHO), it's a long way
from that to claiming that all value types are stored on the stack. Even
"OD" isn't going that far, as near as I can tell.

Pete
Sep 29 '08 #23

P: n/a
On Sep 29, 6:11*am, Arto Viitanen <arto.viita...@microteam.fiwrote:
I think OD is right. When the program sees int, it is always a value
that comes from the stack.
No, that's not true. Consider:

public class Foo
{
int x;

public void Bar()
{
int y = x;
}
}

Now, where does the value y is initialized with come from? The heap -
because that's where the value of x is stored.
There is something on heap that is boxed or
inside a class, but the new int (like the original message asked) is
created onto stack.
The right hand side of the statement in the original question is
(logically, at least) evaluated on the stack. But the target of the
assignment could well be on the heap.

Let's go back to Cor's original statement which I disagreed with:
"Int32 is a structure they never are placed on the heap."

Now consider the class above again:
1) What is the type of the variabe x?
2) Where does its value live, i.e. where is it "placed"?

My answers are "int, i.e. Int32" and "on the heap" - which directly
contradicts Cor's statement.

What are your answers to the above two questions?

Jon
Sep 29 '08 #24

P: n/a
On Sep 29, 6:11*am, Arto Viitanen <arto.viita...@microteam.fiwrote:
I think OD is right. When the program sees int, it is always a value
that comes from the stack.
No, that's not true. Consider:

public class Foo
{
int x;

public void Bar()
{
int y = x;
}
}

Now, where does the value y is initialized with come from? The heap -
because that's where the value of x is stored.
There is something on heap that is boxed or
inside a class, but the new int (like the original message asked) is
created onto stack.
The right hand side of the statement in the original question is
(logically, at least) evaluated on the stack. But the target of the
assignment could well be on the heap.

Let's go back to Cor's original statement which I disagreed with:
"Int32 is a structure they never are placed on the heap."

Now consider the class above again:
1) What is the type of the variabe x?
2) Where does its value live, i.e. where is it "placed"?

My answers are "int, i.e. Int32" and "on the heap" - which directly
contradicts Cor's statement.

What are your answers to the above two questions?

Jon
Sep 29 '08 #25

P: n/a
On Sep 29, 7:06*am, "Jon Skeet [C# MVP]" <sk...@pobox.comwrote:
On Sep 29, 6:11*am, Arto Viitanen <arto.viita...@microteam.fiwrote:
I think OD is right. When the program sees int, it is always a value
that comes from the stack.

No, that's not true. Consider:
<snip>

Apologies for the double post. Not sure what happened there...

Jon
Sep 29 '08 #26

P: n/a
On Sun, 28 Sep 2008 22:32:32 -0700, Jon Skeet [C# MVP] <sk***@pobox.com>
wrote:
Right. Not only is it dangerous in terms of multiple threads, but even
in a single thread I don't see how it could work.

Do you mean in theory? Or based on some specifics about how the CLR
works?
[...]

Well, consider this program:

class Test
{
public static void Main()
{
Action foo = Foo();
foo();
}
public static Action Foo()
{
int i = 5;
return Bar(ref i);
}
public static Action Bar(ref int x)
{
return (Action) delegate()
{
x++;
Console.WriteLine(x);
}
}
}

What would you expect running that to do?
I expect running that would do exactly what you'd expect it to do.
I can't see how it can
compile and run without blowing up (or being unpredictable).
The code you posted can't, I agree. Code that captures a by-reference
variable would have to ensure that it gets used only when the variable is
still present on the stack. Likewise, code that would reference one
thread's stack from another thread would indeed have to be careful to
preserve the stack variable until it's sure the other thread is done using
it.

In C#, it makes perfect sense to prohibit this sort of scenario except in
unsafe code. In C#, one fundamental assumption in the language is that
the language prevents you from accessing invalid data. Whatever else
happens, you can always be assured that the simple act of accessing a
variable isn't going to blow up. But this isn't about what C# _does_ do.
It's about what it might do given alternate rules of engagement.

And given those alternate rules of engagement, it's obvious what it would
mean to access in one thread a by-reference argument passed in another
thread.

That's why I asked the question "Do you mean in theory?" It wasn't clear
to me from your statement "I don't see how it could work" whether you mean
"...in C#", "...in a .NET program", or "...in a hypothetical language that
supports closures, passing by reference, and capturing a by-reference
argument".
The
variable x can't be captured in the normal way, because effectively the
variable itself is being passed in (rather than an initial value).
The language _could_ capture the variable "in the normal way", modulo an
extension of the language that allows it. That is, it could encapsulate
the pointer that a by-reference argument already encapsulates, preserving
it for later use.

Sure, that'd be against C#'s rules, or at the very least, there'd also
have to be some run-time support that has a way of checking to make sure
the referenced variable still exists so that an exception can be thrown if
an invalid attempt to access the variable is made.

But that's very different from saying it simply can't be done.

The bottom line: you can already do the exact same thing using unsafe
code. So obviously, the language and run-time _could_ do something
similar if it fit within the desired design (I'm sure it doesn't fit, but
again...I'm talking about what could happen, not what should happen).

An alternative approach would be to extend the concept of variable
capturing to address the potential of a captured by-reference argument.
It'd be unduly complicated, but it could be done (basically, when
capturing a by-ref argument, the run-time would have to create a captured
data structure that references the existent variable passed by-reference
until that variable no longer exists, at which point the run-time would
copy it to a more conventional captured-variable data structure).

So, that's at least two different approaches that could be used, one of
which would fit fine into the expected behavior of C#. It could be
considered an overcomplication of the language and run-time, but then
there are some pretty complicated "syntactic sugars" in C# (witness
enumerators).
[...]
Well, anything involving pointers would make me suspicious to start
with - and anything relying on a particular stackframe in one thread
still being around by the time another thread executed some code just
sounds pretty evil to me.
For better or worse, .NET already has a specific example that deals with
that situation just fine: Control.Invoke().

The need to execute some specific code on some specific thread is
uncommon, but it does exist. Using normal synchronization mechanisms,
it'd be possible to write code that safely references variables from one
thread's stack in another thread. Is it a "pretty evil hack" for
Control.Invoke() to deliver some code to be executed on one thread, while
it blocks another? That sort of synchronization is all it'd take to
safely use by-reference variables cross-thread. And that's assuming no
language support such as the hypothetical behaviors I've mentioned above.

Pete

p.s. As if all of the above wasn't enough, now I'm sitting here curious
what happens if you pass by-reference a member field of a class. Does the
by-reference argument preserve a reference to the instance of the class
that contains the field? If not, how does C# ensure that the instance
isn't GC'ed before it's done with the by-reference argument? A quick test
suggests that the reference to the containing instance _is_ kept
somewhere, but I haven't had time to research how that happens or why
(i.e. whether it's stipulated in the C# spec).

For example:

class A
{
public int i;
}

void MethodA()
{
A[] rga = new A[1];

rga[0] = new A();
rga[0].i = 5;

MethodB(rga, ref rga[0].i);
}

void MethodB(A[] rga, ref int i)
{
rga[0] = null;
GC.Collect();
Console.WriteLine(i);
}

Interestingly, assuming C# does do this "reference the containing
instance" behavior, it's actually in the same vein as the "safely capture
a by-reference argument" implementation I outlined above. That is, the
compiler has to do some extra work to see where a particular value came
from and handle it accordingly.
Sep 29 '08 #27

P: n/a
On Sep 29, 7:23*am, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:

<snip.
I can't see how it can
compile and run without blowing up (or being unpredictable).

The code you posted can't, I agree. *Code that captures a by-reference *
variable would have to ensure that it gets used only when the variable is*
still present on the stack. *Likewise, code that would reference one *
thread's stack from another thread would indeed have to be careful to *
preserve the stack variable until it's sure the other thread is done using *
it.

In C#, it makes perfect sense to prohibit this sort of scenario except in*
unsafe code. *In C#, one fundamental assumption in the language is that*
the language prevents you from accessing invalid data.
Exactly - and that's what I meant by "I don't see how it could work."
To expand that, "I don't see how it could be permitted and still
remain true to the spirit of C#" :)
>*Whatever else happens, you can always be assured that the simple
act of accessing a variable isn't going to blow up. *But this isn't about
what C# _does_ do. It's about what it might do given alternate rules
of engagement.
True - but when considering "what if we could do X" I usually assume
that the core tenets of the language are adhered to. Anyway, so long
as we understand each other now it doesn't matter too much.

One interesting point would be whether such a program was verifiable.
I haven't looked closely at the verifiability rules. I might do so...

<snip possible approaches - I have nothing more to add there>
[...]
Well, anything involving pointers would make me suspicious to start
with - and anything relying on a particular stackframe in one thread
still being around by the time another thread executed some code just
sounds pretty evil to me.

For better or worse, .NET already has a specific example that deals with *
that situation just fine: Control.Invoke().
Does that really rely on any particular stackframe? In particular, if
the calling thread is interrupted or aborted, I wouldn't expect the UI
thread to suffer corruption - or vice versa. But I do see what you're
getting at, I think.
The need to execute some specific code on some specific thread is *
uncommon, but it does exist. *Using normal synchronization mechanisms, *
it'd be possible to write code that safely references variables from one *
thread's stack in another thread. *Is it a "pretty evil hack" for *
Control.Invoke() to deliver some code to be executed on one thread, while*
it blocks another? *That sort of synchronization is all it'd take to *
safely use by-reference variables cross-thread. *And that's assuming no*
language support such as the hypothetical behaviors I've mentioned above.
Well, it intertwines the threads more tightly than is the case now -
making situations like the above more risky. In the Control.Invoke
situation we're certainly blocking one thread based on another, but
the actual stackframes are still isolated which limits possible
damage. As soon as one stackframe "going away" puts another thread at
risk of corruption, the platform feels less stable.
p.s. *As if all of the above wasn't enough, now I'm sitting here curious *
what happens if you pass by-reference a member field of a class. *Does the *
by-reference argument preserve a reference to the instance of the class *
that contains the field? *If not, how does C# ensure that the instance *
isn't GC'ed before it's done with the by-reference argument? *A quick test *
suggests that the reference to the containing instance _is_ kept *
somewhere, but I haven't had time to research how that happens or why *
(i.e. whether it's stipulated in the C# spec).
Hmm. Interesting question. I really don't know how that's handled.
I'll have a look into it - and see whether the book I'm reading at the
moment (CLR via C#) covers it. (If any non-spec book covers it,
this'll be the one :)

Jon
Sep 29 '08 #28

P: n/a
On Mon, 29 Sep 2008 01:08:10 -0700, Jon Skeet [C# MVP] <sk***@pobox.com>
wrote:
Exactly - and that's what I meant by "I don't see how it could work."
To expand that, "I don't see how it could be permitted and still
remain true to the spirit of C#" :)
Okay...that answers my question for clarification of your statement.
Thanks.
[...]
Does that really rely on any particular stackframe? In particular, if
the calling thread is interrupted or aborted, I wouldn't expect the UI
thread to suffer corruption - or vice versa. But I do see what you're
getting at, I think.
I think you do. :) No, AFAIK Control.Invoke() doesn't currently have any
dependency on a particular stack frame. My only point was that we already
have scenarios in which one thread has a mandate to wait on another. It
does come up, and it's a manageable problem. Yes, with Control.Invoke()
doing so doesn't involve a dependency on the stack, but a program could
have other reasons for relying on the synchronization (i.e. it's not just
a matter of convenience).

Sometimes threads need to wait on others. :)
Well, it intertwines the threads more tightly than is the case now -
making situations like the above more risky.
Yup, true. With great power comes great responsibility. :)
In the Control.Invoke
situation we're certainly blocking one thread based on another, but
the actual stackframes are still isolated which limits possible
damage. As soon as one stackframe "going away" puts another thread at
risk of corruption, the platform feels less stable.
Well, that's why I think if something like this ever showed up in C#, it'd
have to be implemented in a way that removes the dependency on the stack
frame itself. I agree the alternative wouldn't be appropriate in C#.
>p.s. *As if all of the above wasn't enough, now I'm sitting here
curious *
what happens if you pass by-reference a member field of a class. *Does
the *
by-reference argument preserve a reference to the instance of the class
that contains the field? *If not, how does C# ensure that the instance *
isn't GC'ed before it's done with the by-reference argument? *A quick
test *
suggests that the reference to the containing instance _is_ kept *
somewhere, but I haven't had time to research how that happens or why *
(i.e. whether it's stipulated in the C# spec).

Hmm. Interesting question. I really don't know how that's handled.
I'll have a look into it - and see whether the book I'm reading at the
moment (CLR via C#) covers it. (If any non-spec book covers it,
this'll be the one :)
I look forward to hearing whatever you find. It's an intriguing detail I
never thought about before.

Pete
Sep 29 '08 #29

This discussion thread is closed

Replies have been disabled for this discussion.