Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Unbelievable: structs fail their fundamental behavior!

bug struct

  • Please log in to reply
5 replies to this topic

#1 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 18 May 2014 - 05:17 AM

I can't believe my eyes!

:o  :o  :o

 

Here is a simple test:

 

    struct A
    {
        public int X;
        public int Y;
    }


    public class Program
    {
        public static void Main()
        {
            A a, b, c;
            a = b = new A { X = 3, Y = 5 };
            c = a;

            a.X = 8;

            Debug.Print("A: X=" + a.X + "; Y=" + a.Y);
            Debug.Print("B: X=" + b.X + "; Y=" + b.Y);
            Debug.Print("C: X=" + c.X + "; Y=" + c.Y);
            Debug.Print("");
            Debug.Print("A==A =" + a.Equals(a));
            Debug.Print("B==B =" + b.Equals(b));
            Debug.Print("C==C =" + c.Equals(c));
            Debug.Print("");
            Debug.Print("A==B =" + a.Equals(b));
            Debug.Print("A==C =" + a.Equals(c));
            Debug.Print("B==C =" + b.Equals(c));
            Debug.Print("");
            Debug.Print("");



            int r, s, t;
            r = s = 555;
            t = r;

            r = 333;

            Debug.Print("R=" + r);
            Debug.Print("S=" + s);
            Debug.Print("T=" + t);
            Debug.Print("");
            Debug.Print("R==S =" + (r == s));
            Debug.Print("R==T =" + (r == t));


            while (true)
            {
                Thread.Sleep(1000);
            }
        }
    }
The result is the following (Netduino Plus 2; NetMF 4.2):
 
A: X=8; Y=5
B: X=8; Y=5
C: X=3; Y=5
 
A==A =False
B==B =False
C==C =False
 
A==B =False
A==C =False
B==C =False
 
 
R=333
S=555
T=555
 
R==S =False
R==T =False
 
The R-S-T integer test is just for comparison, but behaves fine.
The same snippet ran on regular desktop .Net produces the following (correct) result:
 
A: X=8; Y=5
B: X=3; Y=5
C: X=3; Y=5
 
A==A =True
B==B =True
C==C =True
 
A==B =False
A==C =False
B==C =True
 
 
R=333
S=555
T=555
 
R==S =False
R==T =False
 
Anyone may explain all that???
 

Biggest fault of Netduino? It runs by electricity.

#2 Paul Newton

Paul Newton

    Advanced Member

  • Members
  • PipPipPip
  • 724 posts
  • LocationBerkshire, UK

Posted 18 May 2014 - 06:40 AM

Hi Mario,

 

I don't think the rules for structs and classes are the same.

 

My C# book (a bit old) says structs are "value" types like integers, so they live on the stack.

Classes are "reference" types and live on the heap.

 

So I think when you did a = b = new A (X = 3, Y= 5);

I believe you created b, and then copied it into a.

a and b then do not point/reference the same memory anymore.

 

Try again with a class, instead of a struct and check that the behaviour then works as expected.

 

Paul - about to drive to the rubbish tip with a car full of mud and grass!



#3 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 18 May 2014 - 08:35 AM

Hi Mario,

 

I don't think the rules for structs and classes are the same.

 

My C# book (a bit old) says structs are "value" types like integers, so they live on the stack.

Classes are "reference" types and live on the heap.

 

So I think when you did a = b = new A (X = 3, Y= 5);

I believe you created b, and then copied it into a.

a and b then do not point/reference the same memory anymore.

 

Try again with a class, instead of a struct and check that the behaviour then works as expected.

 

Paul - about to drive to the rubbish tip with a car full of mud and grass!

 

Paul, many thanks for your comment, but...that's exactly what I mean!

The original post's bottom results are for the regular .Net framework, and they're correct at all. A struct is always copied entirely, whereas a class is just referenced with "pointers" (just to understand).

 

If you re-check the Netduino results (right below the snippet) are contradictory.

First off, the "multiple assignment" (or whatever is called) seems creating a class instead of a struct, then "a" and "b" are referring to the same memory area. That is, when you alter "a", also "b" looks altered. That's a clear clue that the objects are *not* two, but just one.

 

Secondly, when I assign "c" from "a" (even before altering "a") the copy looks working fine. The subsequent "a" modification does not alter "c". That's the right way on how the structs should behave.

 

Thirdly, any object should yield "true" when compared to itself.

 

The fourth maybe could be comprehensible, although this is the very first time I noticed it. In the regular .Net you can compare two structs (same type) by simply calling "Equals", without any need to override that method (unless for performance). However it seems that the MS FxCop rules strongly suggests to override and define your own comparison function, because the default implementation leverages the reflection. In this case I may understand that it should be overridden.

 

I may also be in wrong, but the same snippet running on PC evidences the anomaly!

 

Good luck with your car! I refuse to wash it, because the day later is dirty again...


Biggest fault of Netduino? It runs by electricity.

#4 Paul Newton

Paul Newton

    Advanced Member

  • Members
  • PipPipPip
  • 724 posts
  • LocationBerkshire, UK

Posted 19 May 2014 - 06:14 AM

Yes, I missed the change to b, I was concentracting on c.

That will teach me not to answer posts before breakfast. ;-)

 

Do you think this is a problem with the .NetMF or with the port to Netduino?

 

The car stayed quite clean - but evertybody else in Reading had the same idea to go to the rubbish tip at 8am, so there was a big queue!

 

Paul



#5 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 19 May 2014 - 11:41 AM

Yes, I missed the change to b, I was concentracting on c.

That will teach me not to answer posts before breakfast. ;-)

 

Do you think this is a problem with the .NetMF or with the port to Netduino?

 

The car stayed quite clean - but evertybody else in Reading had the same idea to go to the rubbish tip at 8am, so there was a big queue!

 

Paul

 

 

I'd only make an educated guess about the MF, not just Netduino.

Both the struct behavior and the GetHashCode issues sound related to memory management and (maybe) the IL-interpreter.

I'd loved to hear from anyone else having another board (GHI/Mountaineer) and/or another firmware.

 

Car clean...

So you never have the problem of the Sahara's sand flying for thousands of km, then "raining" over the Europe?...Ever had your car orange-shaded?


Biggest fault of Netduino? It runs by electricity.

#6 Paul Newton

Paul Newton

    Advanced Member

  • Members
  • PipPipPip
  • 724 posts
  • LocationBerkshire, UK

Posted 19 May 2014 - 07:59 PM

Yes, orange sand from the Sahara, snow from Siberia, ash from Iceland, floods from Venice, we get it all - but this is England, the rain washes it all away every other day so the car stays clean (but rusty) ;-)







0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.