Can't assign value to structure in array?

J

Jonathan Allen

The increased memory usage of an array of object references (8 bytes heap
overhead per object + 4 bytes per array element pointer) decreases
locality of reference, which also impacts performance.

I still don't think the dereference is significant, but I buy the locality
argument. A poorly timed page fault and everything goes to hell.
 
B

Brett

The object is stored on the heap and GC takes place there. Is the struct
stored on the stack? I'd assume it is since it is value type. Also, how is
the stack cleared? By GC?

Thanks,
Brett
 
J

Jonathan Allen

The object is stored on the heap and GC takes place there. Is the struct
stored on the stack? I'd assume it is since it is value type. Also, how
is the stack cleared? By GC?

The stack is cleared when the function exits. Think of it as a stack of
boxes, the currently running function uses the top-most box. The function
that called it uses the next box. etc. Each box is created with enough room
to hold all the locals declared in the function.

Structs can be stored in the stack or inside a class. Or they can be boxed
and stored as if they were a class.
 
J

Jon Skeet [C# MVP]

Brett said:
The object is stored on the heap and GC takes place there. Is the struct
stored on the stack? I'd assume it is since it is value type. Also, how is
the stack cleared? By GC?

Structs in arrays are stored on the heap (for most .NET applications
anyway; there are ways of storing arrays on the stack in C# and
presumably in C++ too). The stack isn't cleared by the garbage
collector - it's just cleared when the stack is popped. No data which
is on the stack is available after the stack is popped, so there's no
need for a complex system like garbage collection.
 
F

Frank Hileman

We were talking about structs in arrays. Those would always be on the heap,
not the stack. If you are talking about a value type used as a parameter or
local variable, or a temporary returned by an operator overload, then you
are potentially looking at the stack.

The stack is allocated according to the number and size of parameters, local
variables, and temporaries used by a method. When the method returns the
stack space is immediately released and reused for the next method call.
Basically it is just a preallocated block of memory with the current offset
kept in a register than is incremented and decremented. Often temporaries,
local variables, and parameters wind up in registers instead, and take no
space on the stack. This is the ideal situation.

The .NET GC is fast. But it can never beat the memory size and speed of
value types in local variables or parameters, as they may be in registers.
Even if they are on the stack, the .net heap allocater continues to move
into new memory addresses as it allocates new objects, until a GC is
triggered, whereas the stack constantly reuses a smaller area of memory, so
you get better locality of reference. The .NET allocator and GC are so fast
sometimes the heap seems similar to a stack over a larger span of memory.
Look at the timeline view in the CLRProfiler tool.

Regards,
Frank Hileman
 
B

Bruce Wood

My point is that the structure is access only three times. Two writes and
one read. This isn't complicated and I don't have to worry about
accidentally assigning a value to the structure while it is being read
somewhere else. That can't happen since the flow is procedural.
I believe that is the red flag some of you were thinking about.

The "red flag" has nothing to do with concurrency. It has instead to do
with semantics. What's missing in this conversation is that nowhere
have you indicated why you _need_ a struct, rather than a class.
structs in C# are very useful, but they are useful for specific reasons
in specific situations. Nothing you've outlined so far indicates that
you're in one of those situations. You may be, but we just haven't
heard why you need a struct here.

So when do you _need_ a struct?

First and foremost, you need a struct when you need something that will
act like a native (value) type: whenever you assign it, it gets copied.
When you pass it as a method argument, it gets copied. In general you
don't care about the _identity_ of the thing: this-one-versus-that-one;
all you really care about its its _value_ (thus the name). Some
examples of structs I've created: a Fraction class, a Measure class
that holds a quantity and a unit of measure. In both of these cases,
Fractions and Measures act like values, like ints or doubles. I don't
_want_ to have a specific instance of 3 3/4 somewhere, with everyone
pointing to it and modifying it. When I assign a Fraction to a variable
I want to create a new Fraction with the same value.

Second, and less common, you may choose to use a struct to improve the
efficiency of your application. This is the one that gets everyone into
trouble with structs.

A word about efficiency: CPU-intensive applications aside (and there
aren't many of those... really, there aren't), you get far, far more
bang for your buck looking for efficiencies in your program's _design_
than you ever will tweaking code. Yes, there are some areas of
programming where both design and tweaking code are required, but as I
said, not many. It's hard to convince newbies of this. So many new
programmers just _love_ poring over their code, tweaking an instruction
here, eliminating a variable there, obvlivious to the fact that there
are huge gains to be had by modifying design or data structures, and
that all of that hand-work they're doing was probably done by the
compiler or the JITter, anyway.

In C#, this manifests itself as a mad dash to turn things into structs
that really have no business being structs, so that the program will be
"more efficient." It also manifests itself as odd questions in
newsgroups, questions like, "Why would anyone want to use a class if
they're less efficient?" A little knowledge, as the saying goes, is a
dangerous thing.

Of course, in using a struct where a class is really needed, one has to
make the struct mutable (give it set accessors), and then the trouble
really starts.

The "red flag" that Ted Miller mentioned is this: structs are useful,
but you don't often run across situations in which you need them. If
you don't need a struct, you're probably better off using a class,
particularly if you don't have a solid understanding of value semantics
versus reference semantics. The problems you're having are likely an
indication that you really want a class, not a struct.

Furthermore, if you create a mutable struct (a struct with settable
properties), then you had better have a _very_ solid understanding of
value semantics and how they differ from reference semantics.
Otherwise, you're going to find strange things happening in your code,
and the few cycles you may have saved by using a struct (if you save
any at all) will be offset by the hours of head-scratching you'll
endure trying to get your program to work. (The upside is that once
you've gone through that pain, you'll either hate structs or have a
solid understanding of value semantics--or both.)

I would make the same claim about exposing mutable structs as part of
the public contract of a DLL for others' use. You had better be sure
that your callers have a _solid_ understanding of .NET value semantics.
Either that or be ready with arguments as to why you had to make
mutable structs publicly visible. Yes, I know that Microsoft did it.
They had very good reasons why they did it. Nonetheless, it still
confuses the %&$# out of a lot of programmers.

Use classes. Use structs only when classes won't do.
 

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