diff --git a/xml/System.Runtime.InteropServices/Marshal.xml b/xml/System.Runtime.InteropServices/Marshal.xml index beb0c9868ed..23c6401c254 100644 --- a/xml/System.Runtime.InteropServices/Marshal.xml +++ b/xml/System.Runtime.InteropServices/Marshal.xml @@ -4079,7 +4079,16 @@ The code retrieves a reference to an instance of Microsoft Word successfully. Ho ## Remarks The delegate `d` is converted to a function pointer that can be passed to unmanaged code using [the default platform calling convention](/dotnet/standard/native-interop/calling-conventions#platform-default-calling-convention). You can set the calling convention by applying the to the delegate. - You must manually keep the delegate from being collected by the garbage collector from managed code. The garbage collector does not track references to unmanaged code. + You must manually keep the delegate from being collected by the garbage collector from managed code. The garbage collector does not track references to unmanaged code. Use to prevent the delegate from being collected before the native call completes: + + ```csharp + var callback = new MyNativeCallback(MyManagedMethod); + IntPtr fnPtr = Marshal.GetFunctionPointerForDelegate(callback); + NativeMethod(fnPtr); + GC.KeepAlive(callback); // Prevent collection — fnPtr does not root the delegate. + ``` + + If native code stores the function pointer beyond the duration of the call, root the delegate for its entire lifetime — for example, by storing it in a `static` field. This API is unsupported in environments that don't support dynamic entry-point allocation, such as `ProcessDynamicCodePolicy` on Windows, `execmem off` in SELinux, and WebAssembly. @@ -4155,7 +4164,16 @@ The code retrieves a reference to an instance of Microsoft Word successfully. Ho ## Remarks The delegate `d` is converted to a function pointer that can be passed to unmanaged code by using [the default platform calling convention](/dotnet/standard/native-interop/calling-conventions#platform-default-calling-convention). You can set the calling convention by applying the to the delegate. - You must manually keep the delegate from being collected by the garbage collector from managed code. The garbage collector does not track references to unmanaged code. + You must manually keep the delegate from being collected by the garbage collector from managed code. The garbage collector does not track references to unmanaged code. Use to prevent the delegate from being collected before the native call completes: + + ```csharp + var callback = new MyNativeCallback(MyManagedMethod); + IntPtr fnPtr = Marshal.GetFunctionPointerForDelegate(callback); + NativeMethod(fnPtr); + GC.KeepAlive(callback); // Prevent collection — fnPtr does not root the delegate. + ``` + + If native code stores the function pointer beyond the duration of the call, root the delegate for its entire lifetime — for example, by storing it in a `static` field. This API is unsupported in environments that don't support dynamic entry-point allocation, such as `ProcessDynamicCodePolicy` on Windows, `execmem off` in SELinux, and WebAssembly.