Is the fix fixed if an exception is thrown?

I would guess that fixedis realized similarly to using/ try..finallyin the case, if the block ends early (through refund or release of exceptions), the pointer gets the right treatment ( "uncommitted" so that the GC can do their work again).

However, I do not see such a guarantee in the fixed documentation , so I wonder if there is some form of official somewhere, or if I have to enter try..catchin each fixed block.

unsafe void FooUnsafe()
{
    var str = "Foo";
    try
    {
        fixed (char* pStr = str)
        {
            Console.WriteLine("First Char: " + (*pStr));
            throw new Exception("Test");
        }
    }
    catch (Exception ex) {
        Console.WriteLine($"Exception when working with {str}: {ex.Message}");      
    }
}
+4
source share
3 answers

As commented by FCin

, , , # - Dangling Pointer. , . , FooUnsafe .

JuanR

fixed Statement ( #)

.

, Interwebs

private static unsafe void Main()
{
   Console.WriteLine($"Total Memory: {GC.GetTotalMemory(false)}");

   var arr = new int[100000];

   Console.WriteLine($"Total Memory after new : {GC.GetTotalMemory(false)}");

   try
   {

      fixed (int* p = arr)
      {
         *p = 1;
         throw new Exception("rah");
      }

   }
   catch 
   {
   }

   Console.WriteLine($"Generation: {GC.GetGeneration(arr)}, Total Memory: {GC.GetTotalMemory(false)}");

   arr = null;
   GC.Collect();
   GC.WaitForPendingFinalizers();
   Console.WriteLine("Total Memory: {0}", GC.GetTotalMemory(false));
   Console.Read();
}

Total Memory: 29948
Total Memory after new: 438172
Generation: 2, Total Memory: 438172
Total Memory: 29824

IL finally ldnull

.try
{

   // [23 14 - 23 26]
   IL_0043: ldloc.0      // arr
   IL_0044: dup          
   IL_0045: stloc.2      // V_2
   IL_0046: brfalse.s    IL_004d
   IL_0048: ldloc.2      // V_2
   IL_0049: ldlen        
   IL_004a: conv.i4      
   IL_004b: brtrue.s     IL_0052
   IL_004d: ldc.i4.0     
   IL_004e: conv.u       
   IL_004f: stloc.1      // p
   IL_0050: br.s         IL_005b
   IL_0052: ldloc.2      // V_2
   IL_0053: ldc.i4.0     
   IL_0054: ldelema      [mscorlib]System.Int32
   IL_0059: conv.u       
   IL_005a: stloc.1      // p

   ...

} // end of .try
finally
{

   IL_006a: ldnull       
   IL_006b: stloc.2      // V_2
   IL_006c: endfinally   
} // end of finally

: , .

LocalRewriter_FixedStatement.cs Roslyn

// In principle, the cleanup code (i.e. nulling out the pinned variables) is always
// in a finally block.  However, we can optimize finally away (keeping the cleanup
// code) in cases where both of the following are true:
//   1) there are no branches out of the fixed statement; and
//   2) the fixed statement is not in a try block (syntactic or synthesized).
if (IsInTryBlock(node) || HasGotoOut(rewrittenBody))
{

i.e ,

private static unsafe void test(int[] arr)
{
   fixed (int* p = arr)
   {
      *p = 1;
   }
}

.method private hidebysig static void 
   test(
   int32[] arr
   ) cil managed 
{
   .maxstack 2
   .locals init (
   [0] int32* p,
   [1] int32[] pinned V_1
   )

   ...

   IL_001e: ldnull       
   IL_001f: stloc.1      // V_1

   // [54 7 - 54 8]
   IL_0020: ret          

} // end of method MyGCCollectClass::test

ECMA-335 (CLI)

II.7.1.2 , (§II.15.4.1.3). , VES , . , CLI , , , .

[: , . , , , . ]

VES = CLI = CTS = Common Type

, JITer CLR , GC

, GC . GC , , , . , , . GC Compact Phase, , .

, , , GC .

enter image description here

, ( ), ary , , GC .


. , , , ,

+1
+3

.

In a block fixedin the descriptor table, the object will be “pinned”, and the GC will not move the variable unpredictably.

When an exception is thrown, you will exit the fixed scope and the GC will not assume that the memory location is tied.

I don’t know the internal implementation, but GC can check the execution point of a certain thread and based on this find out whether it is allowed to move or not (i.e. based on if within a fixed block or not).

You do not need to have it in a block try/catch/finally.

+2
source

Source: https://habr.com/ru/post/1694831/


All Articles