Показать сообщение отдельно
  #21  
Старый 14.03.2013, 17:17
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

>>Т.е. к сожалению вопрос осталя без ответа - откуда AccessViolation?

Ну даже в коде, который привёл Aristarh Dark, после выделения памяти происходит очистка старого содержимого Dest - вызывается _LStrClr или _UStrClr.
Смотрите что там делается
Запоминается старое значение, которое было в строке
Код:
  Temp:=Pointer(Dest);
здесь используется приведение к Pointer, чтобы убрать "магию" компилятора.
Затем заказывается память под новую строку
Код:
  Pointer(Dest) := _NewUnicodeString(CharLength);
Строка выделяется с уже установленым в 1 счётчиком. Опять "магия" не используется.
Код:
  if Source <> nil then
      Move(Source^, Pointer(Dest)^, CharLength * SizeOf(WideChar)); 
Если был успешный заказ пямяти, то копируем в строку переданный буфер.
Всё как Вы думали.
А затем
Код:
_UStrClr(Temp); 
В самой первой строке процедуры мы запомнили в переменной Temp то, что раньше было в Dest. А далее
Код:
procedure _UStrClr(var S);
asm
        JMP     _LStrClr
end;
просто переход на функцию
Код:
procedure _LStrClr(var S);
{$IFDEF PUREPASCAL}
var
  P: PStrRec;
begin
  if Pointer(S) <> nil then
  begin
    P := Pointer(Integer(S) - Sizeof(StrRec));
    Pointer(S) := nil;
    if P.refCnt > 0 then
      if InterlockedDecrement(P.refCnt) = 0 then
        FreeMem(P);
  end;
end;
{$ELSE}
asm
        { ->    EAX pointer to str      }

        MOV     EDX,[EAX]                       { fetch str                     }
        TEST    EDX,EDX                         { if nil, nothing to do         }
        JE      @@done
        MOV     dword ptr [EAX],0               { clear str                     }
        MOV     ECX,[EDX-skew].StrRec.refCnt    { fetch refCnt                  }
        DEC     ECX                             { if < 0: literal str           }
        JL      @@done
   LOCK DEC     [EDX-skew].StrRec.refCnt        { threadsafe dec refCount       }
        JNE     @@done
        PUSH    EAX
        LEA     EAX,[EDX-skew].StrRec.codePage    { if refCnt now zero, deallocate}
        CALL    _FreeMem
        POP     EAX
@@done:
end;
{$ENDIF}
которая и выполняет пункты 1)-5) из моего первого поста. На шаге 4) и происходит облом.
Ответить с цитированием