Небезопасное манипулирование строками .NET - PullRequest
3 голосов
/ 10 января 2012

Я использую следующий небезопасный код для изменения строки:

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;
        }
    }

Но через некоторое время мой программный сбой C # за исключением:

FatalExecutionEngineError: «Во время выполнения произошла фатальнаяошибка. Адрес ошибки был в 0x6e9a80d9, в потоке 0xcfc. Код ошибки 0xc0000005. Эта ошибка может быть ошибкой в ​​CLR или в небезопасных или не поддающихся проверке частях пользовательского кода. Общие источники этой ошибки включают пользователяошибки маршалинга для COM-взаимодействия или PInvoke, которые могут повредить стек. "

Если я изменю функцию" RemoveLastOne "на" Str1 = Str1.Remove (Str1.Length - 1); "Программа работает нормально.

Почему происходит исключение?И как я могу правильно реализовать небезопасные изменения строки в C #?

Ответы [ 2 ]

7 голосов
/ 10 января 2012

String значения в .Net предназначены для неизменяемости.В этой функции вы принимаете неизменное значение, изменяя его несколькими видимыми способами (содержимое и длина), не говоря уже о записи данных перед оригиналом.Меня совсем не удивляет, что это приведет к более позднему падению CLR, так как в особых случаях String значения в нескольких местах и ​​запись перед указателем просто опасны.

Я действительно не вижу причиныпочему вы хотите сделать небезопасные манипуляции здесь.Безопасный код прост и не вызовет таких типов ошибок.

2 голосов
/ 10 января 2012

Небезопасные манипуляции со строками по своей сути некорректны. Строки .NET не должны редактироваться, и, скорее всего, в фреймворке есть код, построенный на предположении, что строка никогда не изменится. Все, что опирается на String.GetHashCode (), сразу приходит на ум, но могут быть закулисные оптимизации или проверки работоспособности. Предположительно это что-то вроде того, что вызывает ошибку CLR.

Если после профилирования вы обнаружите, что реализация неизменяемой строки в .NET не соответствует вашим потребностям, простейшая изменяемая альтернатива, которая позволит вам изменить ее длину: List<char>.

...