What is the purpose of unsafe command?

Asked

Viewed 577 times

8

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

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

Within the method there seems to be pointer manipulation *, I didn’t know C# supported pointers.


Doubts

I’d like to know what the purpose of command is unsafe and in which situations its use is advised?

2 answers

11


It is not a command but a tag. It serves to instruct the compiler to accept unsafe operations by the programmer.

These operations are mainly:

  • pointer manipulation:
    • operator * to obtain the target value
    • mathematical operators: +, -, ++, -- are the most common
  • obtaining memory address using operator &
  • locking objects to memory for use in unmanaged Apis
    • These Apis are usually Pinvokes, see attribute Dllimport

These resources are said unsafe (insecure) because the compiler has no way to 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, which can bring data that are for example outside the array, or outside the object’s memory area.

When to use?

This feature is used in two situations so I well remember:

  • operations with non-Managed API

    When calling an external non-Managed API and you want to pass a pointer to fill it with something, if the memory has been allocated in a managed way, you must lock the memory positions so that the Garbage Collector does not change the memory of the position object until the lock is released.

  • operations with arrays that require extreme performance

    A practical example is the manipulation of pixel-by-pixel images. It is much faster to iterate pixels without doing any form of array boundary checking.

    Other examples, all include large-scale data manipulation:

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

How to use?

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

The keyword unsafe should be used to mark the method that will be implemented using pointer resources and memory fixation.

And finally you can use the keyword fixed on a pointer, to mark the instance of that object as being fixed. The instruction fixed extends through 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 indicated

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

  • Managed Allocation in Managed Heap:

    The method GetSquare allocates Managed memory in 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 search for a free memory area that is the size of the object to be allocated, and when the object is destroyed by the Garbage Collector, the area used is released, and from time to time the area is compressed, that is, the objects that are in adjacent areas are reorganized to occupy the possible holes that remained in the memory... it is as if it were a defragmentation of the memory.

    So all this way to allocate memory is a little slow compared to the next way the code tests: using stackalloc.

  • Stack Allocation

    The method GetSquareStack allocates memory with stackalloc, which does not use the Heap but the Stack, which is a memory area in which the allocated items are placed one after the other, there is no need to search for a free area. Also, an object can only be deleted from that memory area if it is the last one that resides there. This process of allocating and de-locating memory areas in the stack is done automatically when a method is called or when the method returns safely. The entire stack memory allocated by a method will be automatically released when the method is finished. Thus C# does not allow manually allocating memory in this space because otherwise it would be possible to return an object that resides in this memory, and therefore would be invalidated at the end of this same method.

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

  • Allocation using Marshal.AllocHGlobal

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

    This way of allocating memory is equal to that of Managed Heap in terms of performance. Only GC management that will have no impact.

7

It defines that a block of code (can be a whole method, as in the query syntax) can use language resources considered unsafe.

This is one way to ensure that the feature is not used inadvertently and also allow other parts of the code by default to have a more aggressive optimization given the safety guaranteed.

It allows the use of pointers for memory. Pointers are insecure by nature. It is possible to use arithmetic. There are some limitations, the memory remains managed by Garbage Collector, but access to memory can be done directly to the desired location without further guarantees. This can be useful to give more performance.

If you look at some . NET codes you will see their use. The class String uses enough to achieve maximum performance.

There is also some use of interoperability where the raw pointer is more suitable, me general for performance reasons, but also by specification, typical case of COM and other Windows Apis.

When you need direct disk access (or at least memory mapped files) it is useful.

Bit map manipulation is also an important use.

You can also use fixed to indicate to GC that an object cannot be moved (which can cause memory fragmentation problems, nothing critical, but).

Practically never use it. I never needed it. But I love knowing that the resource is available for the day you need it (I even think I have a situation that I will use).

In general the staff loves to do premature optimization, but luckily this is not a resource often abused.

Its use is only allowed with compiler directive. Another measure not to use inadvertently.

Normally a code like this requires more privileges in the security system of the.NET. The security of the code cannot be verified.

Microsoft documentation.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.