Reputation: 92
In my static main
function I have the following code:
string str1 = "aaaaaaaaa";
pointerTest();
Console.WriteLine( "str1 is: " + str1 );
The static pointerTest
-method, which is declared as unsafe
, contains the following:
string str2 = "aaaaaaaaa";
fixed( char* ptr = str2 )
{
for( int i = 0; i < str2.Length / 3; ++i )
ptr[i] = 'z';
}
Console.WriteLine( "str2 is: " + str2 );
Notice how str1
and str2
are independently declared, but do have the same content.
The expected output of this program would be:
str2 is: zzzaaaaaa
str1 is: aaaaaaaaa
When I run the program the actual output shows this:
str2 is: zzzaaaaaa
str1 is: zzzaaaaaa
When I change str2
or str1
to not have the exact same content (for example by adding one more 'a' at the end of str2
) the program acts like expected.
If have found this behaviour to exist both in .Net Core 3.1 and Mono (unsure about the exact version, I used Repl.It)
My question is why this behaviour happens and what can be done to get around it.
Upvotes: 0
Views: 59
Reputation: 92
My theory is that this happens because of compiler optimization, specifically a process called string interning:
The compiler recognises that it would be unnecessary to allocate str2
by itself, since there already is the exact same sequence of chars in memory, allocated with the initialization of str1
. So instead of allocating it anew, it makes str2
a reference to the location that str1
is already pointing to. More about this can be read here.
Strings are considered immutable in C#, so - under normal circumstances - it shouldn't be possible to modify their content in any way, shape or form.
Since this code is using the unsafe
keyword and pointer-logic it is not guaranteed to not cause undefined behaviour, which leads to the sursprising result.
The only way to get around this "problem" is to adhere to the C#'s specifications and treat Strings as immutable.
Upvotes: 1