-3

Can someone explain why the head and tail is reset to null once second IsAMatch is call even though id pass new pointers to it, the old ones get reset.

I have equivalent script on c++ and it works perfectly.

Any ideas ?
my code

small code example here it prints 10,20 so the second call changes first struct

class Program
{
    static unsafe void Main(string[] args)
    {

        MyStruct* myStruct = null;

        ChangeMe(ref myStruct, 10);

        Console.WriteLine(myStruct->num);

        MyStruct* myStruct2 = null;
        ChangeMe(ref myStruct2,20);

        Console.WriteLine(myStruct->num);

        Console.ReadKey();
    }

    public static unsafe void ChangeMe(ref MyStruct* h, int v)
    {
        MyStruct myStructNew = new MyStruct(v);

        h = &myStructNew;
    }

    public unsafe struct MyStruct
    {
        public int num;

        public MyStruct(int n)
        {
            num = n;
        }
    }
}
IronHide
  • 327
  • 1
  • 3
  • 17
  • You have to remember that .NET uses compacting GC, which means without using [fixed statement](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/fixed-statement), the memory can change between any two instructions (technically GC gets called only on allocation, so on any new call), so your pointers may point somewhere you do not expect them to. Normal references get corrected by the GC, but pointers do not. – MadKarel May 17 '19 at 11:59
  • @MadKarel ok so can make this work as expected ? add fixed statement ? – IronHide May 17 '19 at 12:02
  • @IronHide that depends on what you're actually trying to achieve. This looks a little like an XY problem, which we can best help with if we know what you actually want to happen in addition to your code. I suspect this can be solved without pointers. The code you link to looks as if it's come out of some automated converter, which can be very problematic. – Frauke May 17 '19 at 12:08
  • See my answer, your problem is not with the GC, but with the difference between class and struct in C#. – MadKarel May 17 '19 at 12:11

1 Answers1

2

You are basically returning a pointer to a local variable, which is plain wrong.

There is a difference in C# new keyword and C++ new keyword, or rather between it's interaction with class and struct in C#. In C++, new always means allocation on the heap, which you need to manually dealocate. In C#, new call on class means heap allocation, but new call on struct just initializes local variable.

This C# code:

MyStruct myStructNew = new MyStruct(v);

is equivalent to this C++ code

MyStruct myStructNew{v};

C# struct keyword creates a value type, which means in your case it gets allocated on the stack. Then, after return from ChangeMe, the stack is decremented, deallocating local variables. On second call, stack is incremented again, allocating local variables for the second call. As you are calling the same method, the same stack position will be used for the second MyStruct myStructNew.

MadKarel
  • 299
  • 2
  • 6