Created
August 5, 2018 17:05
-
-
Save ComingNine/8327058dbaf583b617d9917d0e79690b to your computer and use it in GitHub Desktop.
If built with FPC for i386-win32, the application gives "External SIGSEGV". Line 120..130 seems to be the cause...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
program NestedRecordArray_ExternalSIGSEGV; | |
{$I Synopse.inc} // define HASINLINE USETYPEINFO CPU32 CPU64 OWNNORMTOUPPER | |
{$IFOPT D+} {$DEFINE DEBUG} {$ENDIF} | |
{$ASSERTIONS ON} | |
{$IFNDEF FPC} {$APPTYPE CONSOLE} {$ENDIF} | |
uses | |
{$I SynDprUses.inc} // use FastMM4 on older Delphi, or set FPC threads | |
SysUtils, RTLConsts, Classes, Contnrs, | |
SynCommons, SynLog, SynTests, mORMot, | |
SynSQLite3, SynSQLite3Static, mORMotSQLite3; | |
type | |
{$M+} | |
TNestedRecord = packed record | |
DummyString: RawUTF8; | |
end; | |
TNestedRecordArray = array of TNestedRecord; | |
const | |
__TNestedRecord = 'DummyString: RawUTF8'; | |
type | |
{$M+} | |
TOuterRecord = packed record | |
NestedRecordArray: TNestedRecordArray; | |
end; | |
TOuterRecordArray = array of TOuterRecord; | |
const | |
__TOuterRecord = 'NestedRecordArray: array of TNestedRecord'; | |
type | |
{$M+} | |
TSQLMainRecord = class(TSQLRecord) | |
private | |
FOuterRecordArray: TOuterRecordArray; | |
published | |
property OuterRecordArray: TOuterRecordArray read FOuterRecordArray write FOuterRecordArray; | |
end; | |
TTestNestedRecordArray = class(TSynTestCase) | |
published | |
procedure Test; | |
end; | |
TMyTestSuite = class(TSynTests) | |
published | |
procedure RegisterMyTestCases; | |
end; | |
{ TTestNestedRecordArray } | |
procedure TTestNestedRecordArray.Test; | |
var | |
ILog: ISynLog; | |
DateTime: TDateTime; | |
DateTimeStr: string; | |
DBFileName: string; | |
Model: TSQLModel; | |
Rest: TSQLRest; | |
Rec: TSQLMainRecord; | |
RecID: TID; | |
NestedRecord: TNestedRecord; | |
OuterRecord: TOuterRecord; | |
GroupA: TDynArray; | |
JsonName: TFileName; | |
JsonRaw: RawByteString; | |
JsonUTF8: RawUTF8; | |
JsonUTF8Buf: PUTF8Char; | |
JsonValid: Boolean; | |
begin | |
ILog := TSynLog.Enter; | |
DateTime := Now; | |
DateTimeStr := FormatDateTime('yyyy_mm_dd_hh_nn_ss_zzz', DateTime); | |
DBFileName := ExeVersion.ProgramFileName + '.' + DateTimeStr + '.db3'; | |
JsonName := DBFileName + '.json'; | |
TTextWriter.RegisterCustomJSONSerializerFromText(TypeInfo(TNestedRecord), __TNestedRecord); | |
TTextWriter.RegisterCustomJSONSerializerFromText(TypeInfo(TOuterRecord), __TOuterRecord); | |
Model := TSQLModel.Create([TSQLMainRecord]); | |
try | |
Rest := TSQLRestClientDB.Create(Model, nil, DBFileName, TSQLRestServerDB, False); | |
try | |
TSQLRestClientDB(Rest).Server.CreateMissingTables; | |
Rec := TSQLMainRecord.Create; | |
try | |
RecordClear(OuterRecord, TypeInfo(TOuterRecord)); | |
GroupA.Init(TypeInfo(TNestedRecordArray), OuterRecord.NestedRecordArray); | |
RecordClear(NestedRecord, TypeInfo(TNestedRecord)); | |
NestedRecord.DummyString := 'NestedRecord 1'; | |
GroupA.Add(NestedRecord); | |
RecordClear(NestedRecord, TypeInfo(TNestedRecord)); | |
NestedRecord.DummyString := 'NestedRecord 2'; | |
GroupA.Add(NestedRecord); | |
Rec.DynArray('OuterRecordArray').Add(OuterRecord); | |
RecID := Rest.Add(Rec, True); | |
Assert(RecID > 0, 'Error adding the data'); | |
JsonUTF8 := ObjectToJSON(Rec, [woHumanReadable, woStoreClassName]); | |
// JsonRaw := JsonUTF8; | |
JsonRaw := CurrentAnsiConvert.UTF8ToAnsi(JsonUTF8); | |
SynCommons.FileFromString(JsonRaw, JsonName); | |
finally | |
Rec.Free; | |
end; | |
// External SIGSEGV ! | |
Rec := TSQLMainRecord.Create(Rest, RecID); | |
try | |
Check(Rec.DynArray('OuterRecordArray').Count = 1); | |
Check(Length(Rec.OuterRecordArray[0].NestedRecordArray) = 2); | |
Check(Rec.OuterRecordArray[0].NestedRecordArray[0].DummyString = 'NestedRecord 1'); | |
Check(Rec.OuterRecordArray[0].NestedRecordArray[1].DummyString = 'NestedRecord 2'); | |
finally | |
Rec.Free; // No External SIGSEGV if Rec.Free is commented out | |
end; | |
JsonRaw := SynCommons.StringFromFile(JsonName); | |
// JsonUTF8 := JsonRaw; | |
JsonUTF8 := CurrentAnsiConvert.AnsiToUTF8(JsonRaw); | |
JsonUTF8Buf := @JsonUTF8[1]; | |
Rec := JsonToNewObject(JsonUTF8Buf, JsonValid) as TSQLMainRecord; | |
try | |
Check(Rec.DynArray('OuterRecordArray').Count = 1); | |
Check(Length(Rec.OuterRecordArray[0].NestedRecordArray) = 2); | |
Check(Rec.OuterRecordArray[0].NestedRecordArray[0].DummyString = 'NestedRecord 1'); | |
Check(Rec.OuterRecordArray[0].NestedRecordArray[1].DummyString = 'NestedRecord 2'); | |
finally | |
Rec.Free; | |
end; | |
finally | |
Rest.Free; | |
end; | |
finally | |
Model.Free; | |
end; | |
// If there is no exception, delete the temp files. | |
DeleteFile(DBFileName); | |
DeleteFile(JsonName); | |
end; | |
{ TMyTestSuite } | |
procedure TMyTestSuite.RegisterMyTestCases; | |
begin | |
AddCase([TTestNestedRecordArray]); | |
end; | |
begin | |
with TMyTestSuite.Create do | |
begin | |
try | |
Run; | |
finally | |
Free; | |
end; | |
end; | |
end. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment