2

Got doubts with respect to C# static/const member/local variables. Just want to know what happens to the memory allocated to unused static/const member/local variables in C#, how is the memory reclaimed in the following example scenario?

Question is about memory behavior with respect to static and const variables [considering per-App-Domain piece of memory - static storage]? This question is NOT about Garbage Collection. It is about memory and what happens to unused static and const variables that (also) have memory?

Spaghetti Code Snippet:

/// <summary>
/// Skew your data with every-second-and-annoyed updates
/// </summary>
class Skewgle
{
    static Skewgle cloneApele = new Skewgle();
    const Skewgle patentMoto = default(dynamic);
    static int? dontBeEvilMotto = 1998;
    const int ditchMotoToBeEvil = 2014;

    static void Main()
    {
        const Skewgle findYourMailsAlreadyReadBetweenSpamTabs = patentMoto;

        if (findYourMailsAlreadyReadBetweenSpamTabs == null)
        {
            System.Console.WriteLine("findYourMailsAlreadyReadBetweenSpamTabs and patentMoto are null");
        }

        if (cloneApele != null)
        {
            System.Console.WriteLine("cloneApele is not null");
        }

        System.Console.WriteLine("What about dontBeEvilMotto? ditchMotoToBeEvil?");
    }
}

Thanks

user3315496
  • 49
  • 1
  • 4
  • Reworded as suggested. BTW, the question has already been answered well by Alexei Levenkov and Quetzalcoatl. Kudos guys!!! – user3315496 Feb 16 '14 at 10:53

3 Answers3

6

All static fields of a class will be initialized before first usage of any instance/static method of the class (static field initialization in C# spec ).

Static fields are per Application Domain and value will not be marked for GC till unloading of AppDomain.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
4

MSDN: http://msdn.microsoft.com/en-us/library/e6w8fe1b.aspx

A constant expression is an expression that can be fully evaluated at compile time. Therefore, the only possible values for constants of reference types are string and null.

So you cannot have the patentMoto be anything other than null. Btw. default(dynamic) returns exactly null. You could have siply written =null there, it'd be simplier to read. You will never have any non-null "const object variable" other than string. But you can have tons of statics.

The const and static are never GC'ed until the AppDomain that has them in memory is unloaded.

GC by definition cleans up everything that is no longer referenced. Since a static variable remembers some object, that object will NOT be cleaned up as long as the static variable exists. And it exists as long as the containing Type "exists", hence it ceases to exist only when AppDomain is unloaded. Unless you create your own extra appdomains and unload them "manually" at some point of time, it means they are cleaned up at the program's exit.

But, this refers to automatic cleaning up the things the static variable remembers. You can have the thigs released earlier - simply you have to nullify the static variable. GC sweeps objects, not variables. (*)

Obviously, it's not possible for const, so any large const string occupies the memory forever. And regarding the AppDomain - For const it's harder: they are actually compiled into the assembly. So, they will get fully cleaned up only after the assembly is unloaded from memory. If the assembly is shared between appdomains, well, it will stay until the last one is removed. Const are readonly and immutable, so it shouldn't be a pain to share it anyways. Remember that all object const variables are either null or strings. No other options. So unless you create a 4-Gb const string, you don't have to worry about that.

const at local scope does not differ in anything. It's a local 'variable', but it still compiled into the raw assembly. See above.

(*) this means that if you create a class with one million (1000000) of static variables, all null, then their existence will eat that at least ~4MB of memory until the app domain is unloaded. That's because that's one million of null-pointers to be kept. There's nothing to GC in such case, only the Type itself.

quetzalcoatl
  • 32,194
  • 8
  • 68
  • 107
2

The main difference between const and static is the location of memory. All const data is located in the same memory space as executable code which is read-only-memory (ROM), where as static data is loaded into dynamic memory where you can potentially read and write to it. Now here is the interesting part that seems to have been overlooked in each of the previous answers. Static data occupies dynamic memory space but requires additional ROM space and, in the worse case scenario, can take up twice the amount of memory. Consider the following:

class StaticData
{
    static readonly int s_static1 = 1;
    static readonly int s_static2 = 2;
}

class ConstData
{
    const int CONST1 = 1;
    const int CONST2 = 2;
}

The class StaticData has two static variables s_static1 and s_static2 which will occupy dynamic memory space of 2 integers. However they both need to be initialized and therefore there must also exist ROM code to initialize them both. In this example, and depending on the compiler, there would be at least 2 bytes (or 2 integers of storage with no optimizations) of ROM space required just to store the 2 constant values (1 & 2) for initializing the static variables, not to mention the executable ROM code required to initialize them.

For the class ConstData there is only ROM storage space required and therefore this is, in most cases, the best usage of memory.

Now it get more interesting when you consider how the data is used by the compiler. With the exception of string/character data, constants are normally substituted directly in code at the point of reference. In other words the constant values is directly loaded into a register or pushed onto the stack, depending on usage. In the case of a static variable the compiler has to read that value out of memory via additional code (pointer referencing) and therefore additional ROM code is required.

So in summary you are almost always better off using "const" in place of "static readonly".

Donald Fraser
  • 86
  • 1
  • 3