C# Unsafe Code: Why do we need unsafe code in C#?

Unsafe code in C#

In general, the code written in C# is safe code that doesn`t directly access memory using pointers. It also doesn’t allocate raw memory. Instead, managed objects are created.
On the other hand, unsafe code in C# usually refers to a section of code that is not processed by the CLR (Common Language Runtime) and directly access memory using pointers.

Since pointers are complex and might result in memory-related errors like stack overflow, overwritten system memory, etc., extra caution must be taken while handling unsafe code.
By default, pointers are not supported in C#. However, the use of pointer variables is permitted by the unsafe keyword.

charp unsafe code

The Unsafe code is code that uses external resources such as files, music or video files, network streams, etc. With safe code, the GC (garbage collector) frees resources when they are no longer needed. For unsafe code, you should either call GC.Collect() or implement a mechanism to release unused resources.

Pointers

A pointer is a variable that holds the address of another variable or the direct address of the memory location. similar to any variable, a pointer needs to be declared before it can be used to store any variable address.

In C# pointer can only use to hold the memory address of value types and arrays because pointer types are not taken care of garbage collection similar to the reference types.

The garbage collector has no knowledge of pointers or the data they point to. Therefore, a pointer cannot point to a reference or a structure that contains references.

The general syntax for a pointer declaration is:

type* variable_name; // Pointer

Running Unsafe Code

The unsafe keyword can be used to define a block of code that contains unsafe code. A code is considered as unsafe, if it uses the “address of” (&) or pointer operator (*).

Let’s create a simple program to see what will happen if we use pointer without the unsafe keyword:

 static void Main(string[] args)
        {
            int number = 100;
            int* numberPtr = &number;
            Console.WriteLine($"The value of numberPtr is: {numberPtr->ToString() }");
            Console.ReadLine();
        }

When you declare a pointer without using the unsafe keyword, you will get the following error message.

Error message: “Pointers and fixed size buffers may only be used in an unsafe context”

unsafe code in c# example

What exactly is an unsafe context in C#?

In C#, the unsafe features are available only in unsafe contexts. An unsafe context is introduced by including an unsafe modifier in the declaration of a type or member, or by using an unsafe statement such as:

// unsafe statement
unsafe
 {
 int* Pointer;
}

Enable Unsafe Code in Visual Studio IDE

You cannot resolve the unsafe context error by using only unsafe modifiers. The following setting in the project needs to be enabled.

  • Right-click on the project, then select and open the project properties.
  • Select the “Unsafe Code” checkbox under the Build tab.
c# Unsafe code settings

Example:

Let’s declare a section of code inside the main method as unsafe so that we can use pointers without getting any errors.

using System;
namespace CSharp_Unsafe_Code_Example
{
    class Program
    {
        static void Main(string[] args)
        {
           // unsafe block
            unsafe
            {
                int number = 100;
                int* numberPtr = &number;
                Console.WriteLine($"The value of number is: {number}");
                Console.WriteLine($"The value of variable using pointer: {numberPtr->ToString()}");
                Console.WriteLine($"The address of variable is : {(int)numberPtr}");
                Console.ReadLine();
            }
        }
    }
}
   

In the above code, we have declared a pointer variable named  numberPtr , denoted by  int* . Unlike a normal variable which stores a value of any type (int, char, byte, string, etc.), it stores a memory address. We provide this memory address by using the address of operator  (&) . The address of the operator basically returns the address of the variable number.

Here, I am trying to print not only the value of the variable but also the location from where the pointer variable points. The output of the above-mentioned C# unsafe code program is shown below.

c# unsafe code example

Using fixed keyword in an unsafe context

In C#, the  fixed  keyword prevents the garbage collector from disposing or relocating a variable during the execution of the statement body. This can only be used in an unsafe context.The address of a fixed variable doesnot change for the duration of the statement. It can also be used to declare a fixed-size array. The only restriction is that the array type must be bool, byte, char, int, short, ushort, long, sbyte, uint, ulong, float, or double.

Example:

The following program shows how to access array items using pointers:

using System;
namespace CSharp_Fixed_Keyword_Example
{
    class Program
    {    
        static void Main(string[] args)
        {         
            byte[] array = new byte[] { 1, 2, 3, 4};
           // Declaring a code block as unsafe to use pointers.
            unsafe
            {
                fixed (byte* pArray = array)
                {
                    byte* pElement = pArray;
                    foreach (int i in array)
                    {
                        byte value = *pElement;
                        Console.WriteLine($"arr[{i}] at 0x{(uint)pElement:X} is {value}");
                        pElement++;
                    }
                }
            }
            Console.ReadLine();          
        }
    }
}

We will get the following result after running the above program. (It is important to note that the exact memory locations might be different in different executions of the application.)

fixed keyword in unsafe context example

References: MSDN- Unsafe Code

Characteristics of unsafe code

  • The methods, types, class, struct and code blocks can all be defined as unsafe.
  • Use unsafe code whenever you use native functions that require pointers.
  • Unsafe code provides a way to interface with memory.
  • The use of unsafe code introduces security and stability concerns.
  • Code containing unsafe blocks must be compiled with the “AllowUnsafeBlocks” compiler option.

Q: When to use unsafe code in C#?

Ans: Use the unsafe code whenever a program needs to use pointers.

Q: Can a class in C# be marked as unsafe?

Ans: Yes, you can mark a class as unsafe.

Q: How can I enable C# unsafe code?

Ans: Select the solution, then right click on the project to open and explore properties option. Click on the “Build” tab and select the checkbox option “Unsafe Code”.

Q: What is the difference between unsafe and unmanaged code?

Ans: Unmanaged code executes or runs outside the context of CLR. It is not managed by the runtime and hence doesn’t manage by the GC (garbage collector).
While the unsafe code still runs under the context of CLR, it permits us to use the pointers for direct memory access. It is code outside the verifiable subset of CIL (Common Intermediate Language).

Q: What are the disadvantages of Unsafe code in C#?

1. It avoids type-checking, which might occasionally result in errors.
2. It is possible for unsafe code to bypass security and directly access memory locations by using pointers. By default, C# does not allow pointer arithmetic in managed code, unlike C or C++, because the CLR guarantees type safety and security.

Articles to Check Out:

I hope you enjoyed reading this article about “C# Unsafe code“. If you found it useful, please share it with others. If you have any additional information to provide about the topics covered here, do leave a comment.

Leave a Comment