3
votes

I use next unsafe code for string modifying:

public static unsafe void RemoveLastOne(ref string Str1)
    {
        if (Str1.Length < 1)
            return;

        int len = Str1.Length - 1;
        fixed (char* pCh1 = Str1)
        {
            int* pChi1 = (int*)pCh1;
            pCh1[len] = '\0';
            pChi1[-1] = len;
        }
    }

But some time later my C# programm crash with exception:

FatalExecutionEngineError: "The runtime has encountered a fatal error. The address of the error was at 0x6e9a80d9, on thread 0xcfc. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack."

If I change function "RemoveLastOne" to "Str1 = Str1.Remove(Str1.Length - 1);" program works fine.

Why exception happens? And how I can implement unsafe change string in C# correctly?

2
Why would one be doing unmanaged code in a managed environment.? there is truly no need if you are looking to do things such as remove then there is a Replace() method you could use for exampleMethodMan
Just checking, you mean to store an int in a char array at the -1 index? (char is 2 bytes, int is 4 bytes)Kieren Johnstone
pChi1[-1] contains lenght of string in int (4 bytes)Ilya Georgievsky

2 Answers

7
votes

String values in .Net are intended to be immutable. In this function you are taking an immutable value, mutating it in several visible ways (content and length) not to mention writing data before the original. I'm not surprised at all that this would result in a later CLR crash as it special cases String values in several places and writing before the pointer is simply dangerous.

I can't really see a reason why you'd want to do the unsafe manipulation here. The safe code is straight forward and won't cause these types of hard to track down bugs.

2
votes

Unsafe string manipulation is inherently incorrect. .NET strings aren't supposed to be edited, and it's most likely that there is code in the framework that is built around the assumption that a string will never change. Anything that relies on String.GetHashCode() comes immediately to mind, but there might be behind-the-scenes optimizations or sanity checks. Presumably it's something like that which is causing the CLR error.

If you're finding, after profiling, that .NET's immutable string implementation does not fit your needs, the easiest mutable alternative that would let you modify its length is a List<char>.