Creating a Stack-Based Array

No.of Views914
Bookmarked0 times
Downloads 
Votes0
By  Geming Leader   On  16 Feb 2010 02:02:02
Tag : CSharp , PInvoke
By default, arrays are stored in the managed heap with all of the overhead involved and that's because arrays simply are instances of type System.Array that inherits from System.Object. Storing an object into heap means that it will not be removed from the memory until a garbage collection (whether automatic or by calling System.GC.Collect()) occurs. Also, storing it into the heap means suffering from low-performance and the overhead (for the CLR) of storing and retrieving it into and from the h
emailbookmarkadd commentsprint

Images in this article missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at info@codegain.com

 
This article is also available in my blog, Just Like a Magic.

هذه المقالة متوفرة أيضا باللغة العربية، اقرأهاهنا.

Introduction

By default, arrays are stored in the managed heap with all of the overhead involved and that's because arrays simply are instances of type System.Array that inherits from System.Object. Storing an object into heap means that it will not be removed from the memory until a garbage collection (whether automatic or by calling System.GC.Collect()) occurs. Also, storing it into the heap means suffering from low-performance and the overhead (for the CLR) of storing and retrieving it into and from the heap.

To overcome those performance issues and to create short-lived high-performance arrays or even if you want to interoperate with other unmanaged code then you need to work with stack-based arrays. Stack-based arrays stored in the stack. Means high-performance and short-live for the array because we are stepping out the CLR and working with the memory directly.

It might be worth mentioning that types inherit -directly or indirectly- from System.Object are heap-based. Conversely, Types inherit -directly or indirectly- from System.ValueType are stack-based. Although, System.ValueType inherits from System.Object, it is stack-based. Examples of stack-based types are all enumerations, structures, and primitive data types (like Int32 and Boolean).

Creating stack-based arrays

Creating stack-based arrays is very simple. But first, you need to allow unsafe code for the project, and this can be done through the project properties in the Build tab. After that, you can write your code.

The code for creating the stack-based array is as follows:

// Methods that use unsafe code
// must declared as unsafe
// or its containing type
public unsafe static void CreateArray()
{
    int length = 10;

    // Creating Int32 stack-based array
    // with a specific length
    int* pArr = stackalloc int[length];

    // Setting the first value to 1
    *pArr = 1;

    // This code also sets the first value
    // but to 10
    pArr[0] = 10;

    // Setting the second value to 2
    *(pArr + 1) = 2;

    // This code also sets the second value
    // but to 20
    pArr[1] = 20;

    // Retrieving stored values
    Console.WriteLine("First value: {0}", *pArr);
    Console.WriteLine("First value: {0}", pArr[0]);
    Console.WriteLine("Second value: {0}", *(pArr + 1));
    Console.WriteLine("Second value: {0}", pArr[1]);
    Console.WriteLine();

    // Prints:
    // First value: 10
    // First value: 10
    // Second value: 20
    // Second value: 20

    // Setting all values
    for (int idx = 0; idx < length; idx++)
    {
        pArr[idx] = idx + 1;
        // Also this works well
        (pArr + idx) = idx + 1;
    }

    // Retrieving all values
    for (int idx = 0; idx < length; idx++)
        Console.WriteLine("Value {0} = {1}", idx, pArr[idx]);

    // Prints:
    // Value 0 = 1
    // Value 1 = 2
    // ............
    // Value 8 = 9
    //Value 9 = 10

    // The array removed from the memory here
    // Because the scope which
    // it was declared on ends here
}

Code Explanation:

First, we created the array using the stackalloc keyword giving the length for the new array and the type of which is Int32 for our example (you can change it to any value type.) Because Int32 reserves 4-bytes in memory we end up reserving 40 bytes (length 10 multiplied by the Int32 size 4) memory block in the stack for our array.

Stack-Based Array

The last figure shows the pointer returned by the stackalloc, which is always a pointer to the first element of the array. Note that every block is an element of the array. In our example it is 4-bytes. After creating our array putting the last figure into mind we have many ways for accessing array elements.

A note about scope

If you come to this point I think you know well what scope is and how it does affect the code flow. But, I think it is worth noting that you can create new scopes using just two curly brackets. See the following sample class:

public class ClassScope
{
    // Scope 1

    public void Method1()
    {
        // Scope 1.1

        {
            // Scope 1.1.1
            {
                // Scope 1.1.1.1
            }

            {
                // Scope 1.1.1.2
            }
        }
    }

    public void Method2()
    {
        // Scope 1.2

        if (true)
        {
            // Scope 1.2.1

            while (true)
            {
                // Scope 1.2.1.1
            }
        }
    }
}

Quickly copying arrays

It is very handful using pointers to pass the CLR and work directly with memory pointers to copy elements from an array to another the fastest we can. The following code segment does this:

unsafe static void Copy(int[] src, int srcIdx,
    int[] dst, int dstIdx, int count)
{
    // Because normal arrays are heap-based
    // garbage collector can move them
    // from time to time
    // so we use the fixed keyword
    // to stick them and tell
    // the garbage collection to not
    // to move them until fixed
    // statement closes
    fixed (int* pSrc = src, pDst = dst)
    {
        // Getting a pointer to the first
        // element of the array
        int* pSrcIdx = &srcIdx;
        int* pDstIdx = &dstIdx;

        // Ensuring copying the required count only
        for (int counter = 0; counter < count; counter++)
        {
            // Copying....
            // Because Int32 is stack-based
            // it is copied not referenced
            pDst[dstIdx] = pSrc[srcIdx];
            // Moving the pointer to the
            // next element
            dstIdx++;
            srcIdx++;
        }
    }
}

Code explanation:

Because normal arrays are heap-based, it can be moved from its location when a garbage collection occurs, so we tell the CLR that there're references to it, so we do not need it to be moved any where until finishing up.

Honestly, you strictly should avoid using unsafe code when possible. Because, you are working with memory directly. At least you might by mistake overwrite any data stored in the memory without being notified about.

 
Sign Up to vote for this article
 
About Author
 
Geming Leader
Occupation-Software Engineer
Company-Just Like a Magic
Member Type-Expert
Location-Egypt
Joined date-30 Jul 2009
Home Page-http://WithDotNet.net
Blog Page-http://JustLikeAMagic.com
Independent software developer, trainer, and technical writer from Egypt born in 1991
 
 
Other popularSectionarticles
    Today, we are talking about how to move a form without its title bar. You might have noticed that some applications with fancy UIs do not allow the user to move the window from its title bar. Honestly, some hide the overall title bar from the user. An example of these applications is Microsoft Windows Media Player -when in skin mode,- and Microsoft Windows Live Messenger. Both applications allow you to drag their windows using the client area not the title bar. In this lesson, you will lea
    Published Date : 16/Feb/2010
    This lesson focuses on how to programmatically turn on the screen saver.
    Published Date : 16/Feb/2010
    In addition to clearing the console screen, this lesson teaches you some about PInvoking, marshaling, and memory management. Also you will learn additional techniques like clearing a specific portion of the screen, and changing the cursor position. Moreover, you will dig into IL and see how System.Console.Clear() method do it. More than that you will learn how to reverse-engineer a .NET assembly and discover the code inside. In addition, the example shows how to perform I/O operations on cons
    Published Date : 16/Feb/2010
    Swapping mouse buttons means swapping the two buttons, making the right button acts like the left one and vice versa. This is done -for normal users of course- using the Mouse properties dialog in the control panel. See the next figure.
    Published Date : 16/Feb/2010
    Previously, we have talked about how to change screen resolution and color system via DirectX. Today, we are talking about how to change all display settings -not the resolution and color system only- via API. We will change screen resolution (bounds,) color system (bit count,) rotation (orientation,) and refresh rate (frequency) via API with C# and the .NET Framework.
    Published Date : 16/Feb/2010
Comments
There is no comments for this articles.
Leave a Reply
Title:
Display Name:
Email:
(not display in page for the security purphase)
Website:
Message:
Please refresh your screen using Ctrl+F5
If you can't read this number refresh your screen
Please input the anti-spam code that you can read in the image.
^ Scroll to Top