4

Why string pointer position is different each time I ran the application, when I'm using StringBuilder but same when I declare a variable?

void Main()
{
    string str_01 = "my string";
    string str_02 = GetString();
    unsafe 
    {
        fixed (char* pointerToStr_01 = str_01)
        {
            fixed (char* pointerToStr_02 = str_02)
            {
                Console.WriteLine((Int64)pointerToStr_01);
                Console.WriteLine((Int64)pointerToStr_02);
            }
        }
    }
}

private string GetString()
{
    StringBuilder sb = new StringBuilder();
    sb.Append("my string");

    return sb.ToString();
}

Output:

40907812
178488268

next time:

40907812
179023248

next time:

40907812
178448964

Mohamad Shiralizadeh
  • 8,329
  • 6
  • 58
  • 93
  • 2
    why wouldn't it, they are different references? – Selman Genç Jan 07 '15 at 16:45
  • @Selman22 I see but why `StringBuilder` string pointer changes but my varibale doesn't.. – Mohamad Shiralizadeh Jan 07 '15 at 16:46
  • 4
    Not really related but why on earth are you using pointers in C#? – Omada Jan 07 '15 at 16:47
  • @Omada I want to see where my string stores in my RAM? numeric position of it in my system memory or application memory. I want to write a program that find it and change it. Like a cheat application for games. – Mohamad Shiralizadeh Jan 07 '15 at 16:50
  • look into string interning. this may be related with that. since you are initializing `str_01` from a string literal it's interned. But I'm not quite sure why the location doesnt change... – Selman Genç Jan 07 '15 at 16:53
  • @Selman22: With only 3 runs, I wouldn't jump to any conclusions. Run it enough times and it'll probably move. – Matt Burland Jan 07 '15 at 16:55
  • 6
    @Omada Using pointers is perfectly fine in C#; using pointers to managed objects across `fixed` boundaries (as the OP is doing here) is almost never sensible. And expecting pointers to remain fixed for variables across application executions is non-nonsensical in any language. – Servy Jan 07 '15 at 16:56
  • Is this a debug or release build? Do you see the same result for both debug and release? – Matt Burland Jan 07 '15 at 16:59
  • 1
    I'm using **LINQPAD** right now to test.. – Mohamad Shiralizadeh Jan 07 '15 at 17:01
  • @Mohamadshiralizadeh did you try to restart LinqPad between tests? I'd assume location *will* change. Indeed if it single run of LinqPad constants will pick up the same interned instance (and this would be exact duplicate of question I've linked in may likely wrong answer - http://stackoverflow.com/questions/372547/where-do-java-and-net-string-literals-reside) – Alexei Levenkov Jan 07 '15 at 17:09
  • @AlexeiLevenkov I try, same results.. – Mohamad Shiralizadeh Jan 07 '15 at 17:11
  • Where a pointer points physically across different runs of a program is absolutely __none of your business__. Windows is a highly complex system! Don't even try to think about it let alone rely on what you think you see!! – TaW Jan 07 '15 at 17:20
  • @TaW tnx for your good answer... – Mohamad Shiralizadeh Jan 07 '15 at 17:21
  • I agree with @Selman22, maybe in your current context you get the same address over and over again, but change the context a little bit and It may change. Are you asking out of curiosity or do you want to do something specific that depends on the variables being always in the same place? – Dzyann Jan 12 '15 at 19:30
  • @Dzyann out of curiosity... – Mohamad Shiralizadeh Jan 13 '15 at 05:33

4 Answers4

13

str_01 holds a reference to constant string. StringBuilder however builds string instances dynamically, so the returned string instance is not referentially the same instance as the constant string with the same content. System.Object.ReferenceEquals() will return false.

Since the str_01 is a reference to a constant string, its data is probably stored in a data section of the executable, which always gets the same address in the application virtual address space.

Edit:

You can see the "my string" text in UTF-8 encoding when you open the compiled .exe file using PE.Explorer or similar software. It is present in the .data section of the file, including a preferred Virtual Address where the section should be loaded in process virtual memory.

I have however not been able to reproduce that str_01 has a same address on multiple runs of the application, probably because my x64 Windows 8.1 performs Address space layout randomization (ASLR). Because of that, all pointers will be different across multiple runs of the application, even those that point directly to loaded PE sections.

YourSelf
  • 294
  • 3
  • 6
1

Just because two strings are equal that doesn't mean they point to the same references (which I guess would mean having the same pointers), C# does not intern all strings automatically because of performance considerations and what not. If you want the pointers to be the same for both strings you can intern str_02 using string.Intern.

Zache
  • 1,023
  • 6
  • 14
1

when i use fixed it will allocate a memory
as str_01 is constant string, it allocates memory on execution and points to same location every time

fixed (char* pointerToStr_01 = str_01)

but in case of

fixed (char* pointerToStr_02 = str_02)

its dynamically allocating the memory hence the pointing location varies every time

hence there is diffrence in the string pointer each time we run

0

I am not agree that output for

 Console.WriteLine((Int64)pointerToStr_01);

is same for you always as I tested it personally to make my point more clear.

Lets have a look in both cases:

  • In case of string str_01 = "my string", when you will print the pointer value of this variable it will not the same as previous because every time a new String object is created (i.e. string is Immutable) and "my string" is assigned to it. Then within Fixed statement you are printing the pointer's value which is out of scope when you execute the program again and previous value will not be remembered.
  • I think, till now you can self-explain the behavior of StringBuilder.

Also check with:

 string str_01 = GetString();
 private static string GetString()
    {
        var sb = new String(new char[] {'m','y',' ','s','t','r','i','n','g'});
        return sb;
    }
tom
  • 719
  • 1
  • 11
  • 30
  • The first one is actually the same each time, and it makes sense because it's a string stored in the string table of the executable, and is thus probably loaded into the same location each time the program is run. – siride Jan 20 '15 at 14:40