Вызов TJSONUnMarshal.Unmarshal для упорядоченного TStringlist вызывает повреждение памяти?

Этот вопрос должен предоставить MCVE, чтобы проиллюстрировать проблему, обнаруженную в ответе на этот более ранний из моих:

Неожиданный сбой пользовательского зарегистрированного Reverter с использованием TJSONUnMarshal

В моем предыдущем вопросе ответ @VirusTrinity устранил проблему, с которой я столкнулся изначально, а именно то, что объект, полученный в результате операции десортировки, был неправильно возвращен с полем Nil TStringlist. Однако исправление выявило новую проблему, заключающуюся в том, что при завершении работы приложения оно генерирует исключение 0xC0000005, нарушение прав доступа по адресу 0x00000000, чтение адреса 0x00000000. Код ниже показывает это поведение, генерируя тот же AV при выключении по той же причине.

AV, очевидно, возникает из-за повреждения памяти во время выполнения PopulateFields(objFields, Obj, customizer); в function TJSONUnMarshal.CreateObject(JsonObj: TJSONObject): TObject в Data.DBXJSONReflect.

Если вы поместите точку останова там, где показано ниже в коде, добавьте наблюдение за TEncoding.FAnsiEncoding, а затем выполните пошаговое выполнение.

AnObject:= jUnmarshal.Unmarshal(jValue);

вы должны обнаружить, что значение в FMaxCharSize изменяется от 1 до 5 (иногда в предыдущем q я получил 7 вместо 5). Это изменение, по-видимому, является симптомом повреждения памяти, которое, по-видимому, вызывает выключение AV.

Обновление: чтобы увидеть, где происходит AV, поместите точку останова на точку входа в процедуру класса TEncoding.FreeEncodings. Для меня АВ возникает, когда

FreeAndNil(FANSIEncoding);

называется.

Обновление №2: момент, когда TEncoding.FAnsiEncoding повреждается, возникает, когда function TJSONUnMarshal.ClassTypeOf вызывается с параметром Field, имеющим значение FDelimiter, и выполняет оператор.

    fRtti := tRtti.GetField(Field);

Вызов ClassTypeOf из оператора

    else if HasReverter(ComposeKey(ClassTypeOf(Data, FieldName),
    FIELD_ANY)) then

в строке 30222/3023 от procedure TJSONUnMarshal.PopulateFields

Может ли кто-нибудь подтвердить проблему и сообщить, почему это происходит?

Код:

program MATest;

{$APPTYPE CONSOLE}

uses Classes, System.SysUtils, JSon, DBXJson, DBXJSONReflect;

procedure Test;
var
  TL1,
  TL2 : TStringlist;
  AnObject : TObject;
  jMarshal: TJSONMarshal;
  jUnMarshal : TJSonUnMarshal;
  jValue: TJSONValue;
begin
  TL1 := TStringlist.Create;
  TL1.Add('AAA');
  try
    jMarshal := TJSONMarshal.Create(TJSONConverter.Create);

    jValue := jMarshal.Marshal(TL1);
    Writeln(jValue.ToString);

    jUnMarshal := TJSONUnMarshal.Create;  //  < Put breakpoint here and
    //  add watch of TEncoding.FAnsiEncoding in System.SysUtils
    AnObject:= jUnMarshal.UnMarshal(jValue);
    TL2 := TStringlist(AnObject);
    Writeln(TL2.Text);
    Readln;

  finally
    jValue.Free;
    jMarshal.Free;
    jUnMarshal.Free;
    TL1.Free;
    TL2.Free;
  end;
end;

begin
  try
    Test;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

person MartynA    schedule 03.01.2016    source источник
comment
Я отменил редактирование AN Other, чтобы оно относилось к проблеме, обнаруженной в ответе на предыдущий вопрос, потому что мое изменение было преднамеренным и точным - в ответе как таковом не было ничего плохого, он устранил проблему, которую я первоначально задал о.   -  person MartynA    schedule 03.01.2016