Defining a delegate as a function pointer - c#

I am using a delegate which calls an unmanaged function pointer. This causes the Garbage Collector to collect it before it is used, as described in the CallbackOnCollectedDelegate MDA page on MSDN: MSDN page for CallbackOnCollectedDelegate MDA.
The resolution states that I have to marshal the appropriate delegate as an unmanaged function pointer. My initial reflex was to use:
[MarshalAs(UnmanagedType.FunctionPtr)]
public delegate void EntityCallback([MarshalAs(UnmanagedType.SysInt)] IntPtr entity);
However, the C# compiler won't let me marshal a delegate, even if this is the suggested resolution by MSDN. Moreover, the MSDN page only shows an example of the problem being thrown, but not one of the resolution.
How could I marshal my delegate as an unmanaged function pointer or keep it from being GCed?
EDIT: As suggested, I created a reference of the callback. Therefore, my code changed from/to:
// From:
foo.SetCallback(new EntityCallback(bar));
// To:
call = new EntityCallback(bar); // Referenced in class
foo.SetCallback(call);
Now this does work - but only in Debug mode. When I switch to Release, it crashes at the same point. Why is that?
EDIT 2: More complete code snippet:
public class Test
{
private EntityCallback Call;
private void Bar(System.IntPtr target)
{
...
}
public Entity Foo { get; set; }
public Test()
{
this.Foo = new Body.Sphere() { Visible = false }; // Irrelevant
this.Foo.CollisionType = 3; // Irrelevant
this.Call = new EntityCallback(this.Bar);
this.Foo.SetCallback(this.Call, EntityCallbackType.Collision);
}
}

You didn't read it correctly. You must do this:
...change your code to keep a reference
to that delegate on the managed side
for the lifetime of the marshaled
unmanaged function pointer.
In other words, just store a reference to the delegate instance in your class and make sure the class object survives long enough. Use a static if you really have to.

Related

Why local variables are not accessible from other functions?

I'm currently learning about computer memory and asking questions to myself to understand it better.
I learned about how a new space is allocated in the stack whenever a function is called.
But why we can't reach local variables even though they are still on the stack? What is it that prevents me from accessing them while they are still on the stack?
Consider the following code (Please look at the comments):
class Program
{
public static void Main()
{
int number = 5;
Method();
} //<------ number variable will be stored in the stack until the program reaches here.
public static void Method()
{
// number=5 variable is still on the stack so why can't I reach it here?
number = 10; // throws an error because it's not defined in this scope but it's still on the stack.
int anotherNumber = 2;
}
}
In C and languages derived from it, functions are separately compiled so they cannot "see" the local variables of each other. This is a design decision.
In Pascal and languages derived from it, this is made possible by allowing nested function declarations. A function declared inside another sees the local variables of the latter as global ones.
But beware that via mutual and recursive calls, the same variable can exist at several places in the stack.
If that code could compile (i.e. if you comment out number = 10;), the variable number would likely not even be on the stack in a Release build because it's unused and the optimizer would realize that.
C# uses scoping for variables, and the scope of the variable number is the Main() method. If you define it inside the class instead, it'd be a class member and would be accessible also from the method Method(). As a general rule of thumb, though, always try to limit the scope of variables.
class Program
{
static int number = 5; // class member
public static void Main()
{
Method();
}
public static void Method()
{
number = 10; // no error anymore
int anotherNumber = 2;
}
}
variable is still on the stack so why can't I reach it here?
This argument hold as much water as "all variables are in memory so why can't I access from everywhere all variables, including variables from other programs, after all they are all on the same memory right?"
There are so many problems with what you propose. From encapsulation, to name pollution, to optimization, to security.
A local variable is just that: a local variable. It's for me, it's an implementation detail. The outside world should not know about it because since it's mine and I use it for my internal purposes I can change it or remove it at my will. With your proposal what? Now I can't change my own local variable because some function somewhere down the calling chain uses it. And why does it uses it? If I want to pass some information to the function I call then that should be done via parameters.
void foo() { int mine; bar(); }
void bar() { void baz(); }
void baz() { mine = 24; } // like wtf??
Besides how would you handle this situation:
void foo_1()
{
int mine; // I can name it mine because it's a local variable
bar();
}
void foo_2()
{
int mine; // I can also name it mine because it's a local variable
bar();
}
void foo_3()
{
bar();
}
void bar()
{
mine = 24; // ??????
}
In concussion to pass information from one function to another we use parameters, we don't pollute a fictional "global local namespace" because we are not savages.

Unclear behavior by Garbage Collector while collecting instance properties or fields of reachable object

Till today I was thinking that members of reachable objects are also considered to be reachable.
But, today I found one behavior which creates a problem for us either when Optimize Code is checked or application is executed in Release Mode. It is clear that, release mode comes down to the code optimization as well. So, it seems code optimization is reason for this behavior.
Let's take a look to that code:
public class Demo
{
public Action myDelWithMethod = null;
public Demo()
{
myDelWithMethod = new Action(Method);
// ... Pass it to unmanaged library, which will save that delegate and execute during some lifetime
// Check whether object is alive or not after GC
var reference = new WeakReference(myDelWithMethod, false);
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
GC.WaitForPendingFinalizers();
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
Console.WriteLine(reference.IsAlive);
// end - Check whether object is alive or not after GC
}
private void Method() { }
}
I simplified code a bit. Actually, we are using our special delegate, not Action. But the behavior is same. This code is written in mind with "members of reachable objects are also considered to be reachable". But, that delegate will be collected by GC asap. And we have to pass it to some unmanaged library, which will use it for some time.
You can test demo by just adding that line to the Main method:
var p = new Demo();
I can understand the reason of that optimization, but what is the recommended way to prevent such case without creating another function which will use that variable myDelWithMethod which will be called from some place? One, option I found that, it will work if I will set myDelWithMethod in the constructor like so:
myDelWithMethod = () => { };
Then, it won't be collected until owning instance is collected. It seems it can't optimize code in the same way, if lambda expression is setted as a value.
So, will be happy to hear your thoughts. Here are my questions:
Is it right that, members of reachable objects are also considered to
be reachable?
Why it is not collected in case of lambda expression?
Any recommended ways to prevent collection in such cases?
However strange this would sound, JIT is able to treat an object as unreachable even if the object's instance method is being executed - including constructors.
An example would be the following code:
static void Main(string[] args)
{
SomeClass sc = new SomeClass() { Field = new Random().Next() };
sc.DoSomethingElse();
}
class SomeClass
{
public int Field;
public void DoSomethingElse()
{
Console.WriteLine(this.Field.ToString());
// LINE 2: further code, possibly triggering GC
Console.WriteLine("Am I dead?");
}
~SomeClass()
{
Console.WriteLine("Killing...");
}
}
that may print:
615323
Killing...
Am I dead?
This is because of inlining and Eager Root Collection technique - DoSomethingElse method do not use any SomeClass fields, so SomeClass instance is no longer needed after LINE 2.
This happens to code in your constructor. After // ... Pass it to unmanaged library line your Demo instance becomes unreachable, thus its field myDelWithMethod. This answers the first question.
The case of empty lamba expression is different because in such case this lambda is cached in a static field, always reachable:
public class Demo
{
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static Action <>9__1_0;
internal void <.ctor>b__1_0()
{
}
}
public Action myDelWithMethod;
public Demo()
{
myDelWithMethod = (<>c.<>9__1_0 ?? (<>c.<>9__1_0 = new Action(<>c.<>9.<.ctor>b__1_0)));
}
}
Regarding recommended ways in such scenarios, you need to make sure Demo has lifetime long enough to cover all unmanaged code execution. This really depends on your code architecture. You may make Demo static, or use it in a controlled scope related to the unmanaged code scope. It really depends.

Method returns class reference even after termination

I have just started learning C#7.0 from the documentation. I learnt that Class is a reference type. But how can a method return a reference to an object that is already destroyed.
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
public class Program
{
public static void Main()
{
Test b = GetObj();
Console.WriteLine(b.val);
Console.ReadLine();
}
public class Test
{
public int val;
}
public static Test GetObj()
{
Test t = new Test();
t.val = 100;
return t;
}
}
}
Here, method GetObj creates a Test object, and returns it. According to documentation, only a reference to it is returned. So after the function call, t should be collected as garbage, and so b should reference nothing.
But the code still prints 100. Why?
So after the function call,"t" should be collected as garbage, and so "b" should reference nothing.
No. The garbage collector knows how many variables are still referencing that instance, so it isn't garbage collected at all. When there are no variables referencing the instance any more, the garbage collector will kick in.
Not exactly.
When GetObj() is done executing, what is destroyed is the pointer t, not the actual object of type Test.
As you go up the stack, b now points to the object, so the object is not collected because there is a reference to it.
When Main() is done executing, the pointer b will go out of scope and nothing will point to the object anymore so the garbage collector will be able to pick it up (in this case, the end of the program execution).

C# passing class member as ref parameter

I do not understand why it is possible to pass a class instance member as ref parameter to a function.
The object could be moved by garbage collection while the function is executing, invalidating the reference.
Yet this seems to be allowed and works. Does it mean "ref" parameters are more than just a native pointer under the hood?
class A
{
public int Value;
}
class Test
{
static void F(ref int value)
{
value = 7;
}
static void Main()
{
A obj = new A();
// obj can be moved by GC, so "ref obj.Value" cannot be a native pointer under the hood
F(ref obj.Value);
System.Console.WriteLine(obj.Value); // Prints 7
}
}
Does it mean "ref" parameters are more than just a native pointer under the hood?
Yes, that's exactly what it means. If it were just a pointer, they'd call it a pointer instead of a reference. Instead, for references the GC knows about the original object and correctly tracks things, so the reference stays with the object and the object won't be collected until the method exits.

Potential pitfalls with static constructors in C#

My question comes after refactoring a class that contained only static methods to be declared as a static class, and experiencing weird issues when starting the application.
I have not performed any thorough investigation but it seems that some call being made from within the static constructor does not complete for some reason.
So, I would like to know where there are any pitfalls when using static constructors in C#? More specifically, are there any things that should be avoided at all cost and not be used from within the static constructor?
There are several pitfalls to static constructors. For example, if a static constructor throws an exception, you would continue getting a TypeInitializationException whenever you access any of its members.
If a static constructor throws an exception, the runtime will not invoke it a second time, and the type will remain uninitialized for the lifetime of the application domain in which your program is running.
In general, static classes should only be used in stateless scenarios where you won’t need any initialization. If your class needs to be initialized, you might be better off using the singleton pattern, which can be lazily initialized on first access:
public class MyClass
{
private static readonly Lazy<MyClass> current =
new Lazy<MyClass>(() => new MyClass());
public static MyClass Current
{
get { return current.Value; }
}
private MyClass()
{
// Initialization goes here.
}
public void Foo()
{
// ...
}
public void Bar()
{
// ...
}
}
static void Main(string[] args)
{
MyClass.Current.Foo(); // Initialization only performed here.
MyClass.Current.Bar();
MyClass.Current.Foo();
}
Edit: I did some further reading up on the matter, and it appears that static constructors do cause deadlocks if you perform blocking operations (e.g. asynchronous callbacks or thread synchronization) within them.
The CLR internally uses locking to prevent type initializers (static constructors) from being executed multiple times concurrently. Thus, if your static constructor attempts to access another member of its declaring type from another thread, it would inevitably deadlock. Since “another member” could be an anonymous function declared as part of a PLINQ or TPL operation, these bugs can be subtle and hard to identify.
Igor Ostrovsky (MSFT) explains this in his Static constructor deadlocks article, providing the following example of a deadlock:
using System.Threading;
class MyClass
{
static void Main() { /* Won’t run... the static constructor deadlocks */ }
static MyClass()
{
Thread thread = new Thread(arg => { });
thread.Start();
thread.Join();
}
}
In the above example, the new thread needs to access the empty anonymous function, { }, defined as its callback. However, since the anonymous function is compiled as another private method of MyClass behind the scenes, the new thread cannot access it before the MyClass type initializes. And, since the MyClass static constructor needs to wait for the new thread to complete first (because of thread.Join()), a deadlock ensues.
Yes, there are some pitfalls, mostly related to when the class is initialized. Basically, a class with a static constructor will not be marked with the beforefieldinit flag, which allows the runtime to initialize it at a later time.
Have a look at this article for more details.
This is not an answer to the question, but it's too long for a comment, so I offer it here...
Since I didn't know for static class construct, I have used following scheme (simplified) to provide me with singletons:
public class SomeSingleton {
static _instance;
static public SomeSingleton Instance {
get {
if (_instance==null) {
_instance=new SomeSingleton();
}
return _instance;
}
}
}
Later, you use
SomeSingleton.Instance.MyProp = 3;
And first usage of the Instance member will construct your singleton.
I guess that it is OK since instantiation of the singletons if there are many of such classes is done in proper order.

Categories

Resources