This q should provide MCVE to illustrate the problem discovered by the answer to my previous one:
Unexpected user registered reverter crashes using TJSONUnMarshal
In my previous q, an answer from @VirusTrinity fixed a problem that I was initially confronted with, namely, that the object obtained using the expand operation was incorrectly returned with the Nil TStringlist field. However, the fix revealed a new problem, which is that when the application terminates, it throws an exception 0xC0000005, violation of access rights to the address 0x00000000 to read the address 0x00000000. The code below shows this behavior, generating the same AV on shutdown, for the same reason.
AV, obviously, is due to memory corruption during the execution of PopulateFields(objFields, Obj, customizer); in function TJSONUnMarshal.CreateObject(JsonObj: TJSONObject): TObject in Data.DBXJSONReflect.
If you place a breakpoint as shown in the code below, add a clock to TEncoding.FAnsiEncoding, and then one-step
AnObject:= jUnmarshal.Unmarshal(jValue);
you should find that the value in FMaxCharSize changes from 1 to 5 (sometimes in the previous q I got 7 instead of 5). This change seems to be a symptom of memory corruption, which seems to lead to mute AV.
Update:. To find out where the AV is, place a breakpoint at the entry point to the TEncoding.FreeEncodings class procedure. For me, AV occurs when
FreeAndNil(FANSIEncoding);
.
Update # 2: The point where TEncoding.FAnsiEncoding gets corrupted is when function TJSONUnMarshal.ClassTypeOf is called with the Field parameter set to FDelimiter and executes the statement
fRtti := tRtti.GetField(Field);
Call ClassTypeOf from an expression
else if HasReverter(ComposeKey(ClassTypeOf(Data, FieldName), FIELD_ANY)) then
on line 30222/3023 of procedure TJSONUnMarshal.PopulateFields
Can someone confirm this problem and tell why it is happening?
code:
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.