开发者

Dangers of converting delegates to function pointers

开发者 https://www.devze.com 2023-01-24 19:56 出处:网络
Suppose you have a managed class that converts a delegate member to a native function pointer and hands it to native code.Assume that the class/delegate stays in scope and does not change for the life

Suppose you have a managed class that converts a delegate member to a native function pointer and hands it to native code. Assume that the class/delegate stays in scope and does not change for the lifetime of the native code (so that will not be obviousl开发者_如何学JAVAy destroyed by the GC). What other problems should one be aware of in this situation? For example, is it possible for the GC to move the delegate or the actual method the delegate refers to and leave your native code with an access violation?


It seems that it's possible to pin the memory location of the delegate/function, but this obstructs a major advantage of the .NET GC: compacting.

Once a GC sweep is done, every object is relocated in memory to be contiguous. This makes both access and allocation faster that it would be if the heap were fragmented. If you have to pin an object in place in the heap, the GC would have to work around it and if it were done multiple times, it could lead to some nontrivial heap fragmentation. (By the way, this is addressed with GCHandle in the article linked by Ron Warholic. I'm not sure if that is available outside managed C++.)


I'm not much of a .Net expert, but I think you should take a look here : Marshal Callbacks and Delegates Using C++ Interop.

Notice that is it possible, but not necessary, to pin the delegate using pin_ptr to prevent it from being re-located or disposed of by the garbage collector. Protection from premature garbage collection is needed, but pinning provides more protection than is necessary, as it prevents collection but also prevents relocation.


The GC can move the delegate, but not the native code the delegate wraps. So as long as the delegate is not collected the function pointer will remain valid.

Note that "being in scope" is not sufficient to keep an object from being collected. It has to be used (possibly by a call to GC.KeepAlive).


A quick search reveals some Microsoft guidance on the issue. The article is for managed C++ but the guidance should hold for any language on the CLR.

The idea is that you need to prevent the delegate itself from being relocated or disposed but (naturally) the underlying code cannot move. Once the JIT compiles to native code that code is fixed and should not move.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号