Этот вопрос должен предоставить 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.