c# – What is the purpose of the unsafe command?

Question:

I saw the use of the unsafe command in this code in the declaration of this method:

public unsafe static int GetSquareStack(int value) {...}

Inside the method there seems to be handling of pointers * , I didn't know that C# supported pointers.


Doubts

I would like to know what is the purpose of the unsafe command and in what situations is it advisable to use it?

Answer:

It's not so much a command as a tag. It serves to instruct the compiler to accept so-called unsafe operations by the programmer.

These operations are mainly:

  • pointer manipulation:
    • operator * to get the pointed value
    • mathematical operators: + , - , ++ , -- are the most common
  • getting memory address using & operator
  • locking objects in memory for use in unmanaged APIs
    • these APIs are usually PInvokes, see DllImport attribute

These features are said to be unsafe (unsafe) because the compiler cannot guarantee that the programmer will always be accessing valid memory addresses… after all, it is possible to put any value in a pointer and try to access it, which can bring data that is, for example outside the array, or outside the object's memory area.

When to use?

This feature is used in two situations as far as I remember:

  • unmanaged API operations

    When you call an unmanaged external API and you want to pass a pointer to it to fill with something, if the memory has been allocated in a managed way, you must lock the memory locations so that the Garbage Collector doesn't change the memory of the object. position until the lock is released.

  • operations with arrays that demand extreme performance

    A practical example is the manipulation of images pixel by pixel. It's much faster to iterate through the pixels without doing any form of array bounds checking.

    Other examples all include large-scale data manipulation:

    • data compression
    • data encryption
    • Hash calculation of data including signatures
    • works with audio data
    • etc.

How to use?

First, the project needs to be marked as containing unsafe code. This is necessary because the generated assembly will have greater restrictions on its use, so that in certain contexts an error in use can compromise the process that is using the assembly. For example, imagine loading an unsafe assembly into SQL Server, it cannot let any user do it without sufficient authorization.

The unsafe keyword should be used to mark the method that will be implemented using pointers and memory pinning features.

And finally you can use the fixed keyword on a pointer, to mark the instance of that object as being fixed. The fixed statement extends over an execution block, at the end of which the object instance is released to be moved by the Garbage Collector.

What does it mean in the code you entered

In the code you indicated the resource utilization is to compare performance between two ways of allocating memory for an array. However, there are still other ways to allocate memory besides these. I will list them:

  • Managed allocation on the Managed Heap:

    The GetSquare method allocates managed memory on the Managed Heap, which is like an arbitrary collection of objects, which can be created and destroyed. When an object is created, the allocator has to look for an area of ​​free memory that is the size of the object to be allocated, and when the object is destroyed by the Garbage Collector, the used area is released, and from time to time the area it is compressed, that is, the objects that are in adjacent areas are rearranged to occupy the possible holes that were left in the memory… it is like a memory defragmentation.

    So all this way of allocating memory is a bit slow compared to the next way the code tests: using stackalloc .

  • Stack allocation

    The GetSquareStack method allocates memory with stackalloc , which does not use the Heap but the Stack, which is an area of ​​memory where allocated items are placed one after the other, there is no need to search for a free area. Furthermore, an object can only be deleted from this memory area if it is the last one that resides there. This process of allocating and deallocating areas of memory on the heap is done automatically when a method is called or when the method safely returns. All heap memory allocated by a method will automatically be freed when the method ends. Therefore, C# does not allow you to manually allocate memory in this space, otherwise it would be possible to return an object that resides in this memory, and therefore it would be invalidated at the end of this same method.

    This is why stackalloc is not secure. Memory is being allocated and a pointer is obtained, which at the end of the method will be invalidated. But still, as the programmer got his hands on this pointer, he can now return this pointer, which will be invalid outside the method.

  • Allocation using Marshal.AllocHGlobal

    This form of memory allocation will allocate on the unmanaged Global Heap. The Garbage Collector has no influence over this memory area, so everything allocated there is already fixed by nature.

    This way of allocating memory is the same as the Managed Heap in terms of performance. Only management by the GC will have no impact.

Scroll to Top