Web Design that taps into the haromny and vision of your dreams.

Unsafe Code Execution in Microsoft .Net

How to execute unsafe code in a managed environment

Written By on in C#

868 words, estimated reading time 4 minutes.

C# and any other .Net language is a managed environment. This means that, among other things, in the background, a hidden process called the Garbage Collector cleans up unused memory and old references to make room for new.

Advanced C# Programming Series
  1. C# Advanced Data Types
  2. Using C# Properties and Indexers
  3. C# Event Handling and Delegates
  4. Method Overloading and Overriding in C#
  5. C# Class Abstraction and Encapsulation
  6. C# Aggregation and Advanced Scope Techniques
  7. Polymorphism in C#
  8. Boxing and Unboxing Value Types in C#
  9. C# Operator Overloading
  10. Creating Multi-Threading Applications with C#
  11. Unsafe Code Execution in Microsoft .Net

Managed code is the direct responsibility of the .Net CLR which looks over things like memory management. The problem with managed code is the garbage collector process that removes unused memory locations and references and will cause other pointers to change reference as a result. For this reason pointers are only allowed within the unsafe code block.

By marking a section of code as "unsafe" you take away this responsibility from the CLR to the programmer. It is now the coder's responsibility to clean up objects and memory after they are used. The advantage of this method is that code is much faster to execute as a lot of the overhead of managed code is eliminated.

Defining Unsafe Code

You are required to mark code as "unsafe" to prevent accidental use of pointers (especially from C++ programmers). Unsafe code can be marked by simply enclosing a section of code in a unsafe block:

...
unsafe
{
...
// this code is unsafe - pointers can be used.
...
}
...

Unsafe can also be used as an access modifier when declaring methods:

unsafe public static void myUnsafeMethod
{
...
// this code is unsafe - pointers can be used.
...
}

Pointer Notation

As well as specifying blocks of code as unsafe, you must also tell the compiler that you want to allow unsafe code blocks to be executed. This is done from within the project options. Under the Project menu select Properties and under the Build tab there is an option to "Allow unsafe code blocks". Once this is set and you are within an unsafe code block you can use pointers. This should give you an indication of how dangerous pointers are.

Pointers are declared in the same was as in C++.

int normalInteger;
int *pointerInteger;

Note the use of an asterisk before the variable name. In this example, normalInteger is assigned the value of an integer (default = 0) , whereas pointerInteger is assigned the memory location of an integer. The asterisk can also be placed after the type, e.g. int* pointerInteger.

What is a Pointer?

A normal variable is a container that holds information of a particular type (int, string, enum and so on). A pointer variable does not hold a value or a type, but instead, it contains a memory location that points to the container. When you read and write to a pointer variable you are getting and setting the memory location (also known as an address).

Pointers and Memory Locations in C#
Pointers and Memory Locations in C#

In the above diagram, we can see 5 memory locations, each with a type and a value. The size and length of the memory location will vary depending on the size of the type used, for example, an integer is a 4-byte value type, so each memory location of type int is 4 bytes long.

If we declare a standard variable, e.g. int myInt = 52432, then the container identified as myInt contains the value 52432. This value cannot be changed, so we say that it is an immutable type. When you re-assign a value to it later, e.g. myInt = 89343, another int type is created and myInto points to that value. This is true for all value types.

When we declare a pointer to an int, e.g. int *myInt, we are assigning the container myInt the memory location of 4 available bytes in memory, in this case, 5. In reality, there are many hundreds of thousands of memory addresses which are represented in hex. For simplicity, we are just using simple numbers.

If you were to assign a value to a pointer type, e.g.

int *myInt;
myInt = 2;

Then you are assigning a different memory location to the variable. In this example, myInt now points to memory location 2, which is a string. Because integers are 4 bytes long, when you try and access the value of the pointer, it will only return the first 4 bytes of the string. If you assign to the pointer then the original string will become corrupt.

By changing pointers around it is very easy to corrupt or overwrite data in memory and cause the operating system to error or even crash. This is why pointers are dangerous and should only be used when it is essential to use them. There are valid reasons for using pointers, for example, applications which feature large numbers of complex mathematical operations where speed is paramount - i.e. a device driver.

Basic usage of Pointers

Pointers are used slightly different to normal variables. If you use a pointer as you would a variable then you will more than likely cause memory corruption.

unsafe
{
  int* x;
  int y = 10;
  x = &y;  
  Console.WriteLine("Value of x is: " + *x);
}

Value of x is: 10

Fixed Keyword

The Garbage Collector will re-arrange memory locations as it cleans up, causing a problem with pointers to objects being moved but the pointer still points to the old location. To overcome this problem there is a fixed keyword that can be used to pin the object and makes sure that the garbage collector will not relocate the object.

Color cl = new Color();
unsafe
{
  Console.WriteLine("Red Component of Color is: {0}", cl.R);
  fixed (byte *pRed = &cl.R)
  {
    *pRed = 122;
  }
  Console.WriteLine("Red Component of Color is: {0}", cl.R);
}

Last updated on: Friday 23rd June 2017

 

Comments
Mini

Mini

When a code block is used with 'Unsafe' its the reponsibility of coders to clean up the unwanted objects memory locations within that block and not that of CLR.In that case how the garbage collector can affect the objects within a 'Unsafe' block? This seems to be a little bit confusing for me.Really need someone's opinion on this.

Reply to Mini
Tim Trott

Tim Trott

Usually after you create an instance of a class and it is no longer in scope the garbage collector will dispose of the object and free up memory. With unsafe code block you must do this yourself, i.e. calling the dispose method or setting value types to null.

Reply to Tim Trott

 

Leave a Reply

Your email address will not be published.





If you find something abusive or that does not comply with our terms or guidelines please flag it as inappropriate.

Copyright © 2001-2018 Tim Trott, all rights reserved. Web Design by Azulia Designs

This web page is licensed for your personal, private, non-commercial use only.

Disclaimer, Privacy & LegalSitemapContact Me