I came across “CorruptedString” (Solution). Here is following code of program from the book:
var s = "Hello";
string.Intern(s);
unsafe
{
fixed (char* c = s)
for (int i = 0; i < s.Length; i++)
c[i] = 'a';
}
Console.WriteLine("Hello"); // Displays: "aaaaa"
Why does this program display "aaaaa"? I understand this program as follows:
string.Intern(s)
actually does nothing, because the CLR had reserved "Hello" string - it just returns address of reserved "Hello" string (object s has the same address)As I understand the intern pool, it is like some kind of dictionary of string to string. Or maybe I missed something?
When you use "Hello" for the first time, it's interned into the application global store of strings.
Based on the fact you're executing in unsafe
mode (more about unsafe
here) you obtain a direct reference to data stored in the locations originally allocated for the value of string s
, so by
for (int i = 0; i < s.Length; i++)
c[i] = 'a';
you're editing what's in memory. When it accesses the store of interned strings next time, it will use the same address in memory, holding the data you've just changed. That would not be possible without unsafe
. string.Intern(s);
doesn't play a role here; it behaves the same if you comment it out.
Then by
Console.WriteLine("Hello"); // Displays: "aaaaa"
.NET
looks at whether there is an entry for an address obtained for "Hello"
and there is: the one which you've just updated to be "aaaaa"
. The number of 'a'
characters is determined by the length of "Hello"
.
Even though @Jaroslav Kadlec answer is correct and complete I would like to add some more information about the behaviour of the code and why string.Intern(s);
is useless in this case.
Actually .NET automatically execute string interning for all string literals, this is done by using a special table that stores references to all unique strings in our application.
However it's important to notice that only explicitly declared string are interned on the compile stage.
Consider the following code:
var first = "Hello"; //Will be interned
var second = "World"; //Will be interned
var third = first + second; //Will not be interned
Of course in some circumstances we would like to intern some string at run-time and this can be done by String.Intern
after checking with String.IsInterned
.
So coming back to the snippet of the OP:
//...
var s = "Hello";
string.Intern(s);
//...
In this case string.Intern(s);
is useless as it's already interned at compile stage.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With