Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 09/09/20 in all areas

  1. haentschman

    Delphi 10.4 (.1) Welcome Page

    Hi... the solution ist here... https://www.danielwolf.eu/blog/2015/1668-meine-vorstellung-einer-willkommens-seite ...slim and effective
  2. Darian Miller

    Delphi 10.4 (.1) Welcome Page

    +1. I use a manual batch file or an automated script. Part of the batch file: echo add LiveBinding set of packages to list of globally disabled packages as they slow down form editing and am currently not using reg add "HKEY_CURRENT_USER\Software\Embarcadero\BDS\21.0\Disabled Packages" /v "$(BDSBIN)\dclbindcomp270.bpl" /t REG_SZ /d "Embarcadero LiveBindings Components" /f reg add "HKEY_CURRENT_USER\Software\Embarcadero\BDS\21.0\Disabled Packages" /v "$(BDSBIN)\dclbindcompfmx270.bpl" /t REG_SZ /d "Embarcadero LiveBindings Components FireMonkey" /f reg add "HKEY_CURRENT_USER\Software\Embarcadero\BDS\21.0\Disabled Packages" /v "$(BDSBIN)\dclbindcompvcl270.bpl" /t REG_SZ /d "Embarcadero LiveBindings Components VCL" /f reg add "HKEY_CURRENT_USER\Software\Embarcadero\BDS\21.0\Disabled Packages" /v "$(BDSBIN)\dclbindcompdbx270.bpl" /t REG_SZ /d "LiveBindings Expression Components DbExpress" /f reg add "HKEY_CURRENT_USER\Software\Embarcadero\BDS\21.0\Disabled Packages" /v "$(BDSBIN)\dclbindcompfiredac270.bpl" /t REG_SZ /d "LiveBinding Expression Components FireDac" /f reg add "HKEY_CURRENT_USER\Software\Embarcadero\BDS\21.0\Disabled Packages" /v "$(BDSBIN)\dclbindcomp270.bpl" /t REG_SZ /d "Embarcadero LiveBindings Components" /f echo Prefix description with an underscore to disable known IDE packages - added suffix signifying intentionally disabled reg add "HKEY_CURRENT_USER\Software\Embarcadero\BDS\21.0\Known IDE Packages" /v "$(BDS)\Bin\GuidedTour270.bpl" /t REG_SZ /d "_Embarcadero Guided Tour Package (Intentionally Disabled)" /f reg add "HKEY_CURRENT_USER\Software\Embarcadero\BDS\21.0\Known IDE Packages" /v "$(BDS)\Bin\startpageide270.bpl" /t REG_SZ /d "_Start Page IDE Package (Intentionally Disabled)" /f reg add "HKEY_CURRENT_USER\Software\Embarcadero\BDS\21.0\Known IDE Packages" /v "$(BDS)\Bin\TrackingSystem270.bpl" /t REG_SZ /d "_Embarcadero Tracking System Package (Intentionally Disabled)" /f pause reg add "HKEY_CURRENT_USER\Software\Embarcadero\BDS\21.0\Editor\Options" /v "Visible Right Margin" /t REG_SZ /d "False" /f reg add "HKEY_CURRENT_USER\Software\Embarcadero\BDS\21.0\Debugging\Embarcadero Debuggers" /v "Break On Language Exceptions" /t REG_SZ /d "0" /f
  3. FPiette

    Record Alignement and Delphi 10.4.1

    Before writing a report at Embarcadero Quality Portal, I suggest that you debug the code by yourself. You probably know it much than me. Since you don't have D10.4.1, I can arrange a TeamViewer session for you on my computer so that you debug it. Let me know if you are interested.
  4. Just my 2-cents worth - I prefer to use something more like this: type PDataRec = ^TDataRec TDataRec = record DataID: integer; DataName: string; end; var Data: TArray<TDataRec>; function FindRecord(aID: Integer): PDataRec; var i: Integer; begin Result := nil; for i := Low(Data) to High(Data) do begin if Data[i].DataID = aID then begin Result := @Data[i]; Exit; end; end; end; function AddRecord(aID: Integer): PDataRec; var vNewData: TDataRec; begin vNewData := Default(TDataRec); vNewData.DataID := aID; Data := Data + [vNewData]; Result := @Data[High(Data)]; end; function EnsureRecord(aID: Integer): PDataRec; begin Result := FindRecord(aID); if Result = nil then Result := AddRecord(aID); end; procedure SaveData1(aID: Integer; const aName: string); var pData: PDataRec; begin pData := EnsureRecord(aID); pData.DataName := aName; end;
  5. Stefan Glienke

    Record Alignement and Delphi 10.4.1

    Reported: https://quality.embarcadero.com/browse/RSP-30890
  6. Personally I see nothing wrong with using exit there. I usually add a comment to it to make it more visible. procedure SaveData2(aID: Integer; const aName: string); var i: Integer; vNewData: TDataRec; begin for i := Low(Data) to High(Data) do if Data[i].DataID = aID then begin Data[i].DataName := aName; Exit; //==> end; // Save new Data rec, if ID not found // ... end; (But people have criticized me for adding that comment.) Of course purists will tell you that exit is just a goto in disguise and that "everybody knows that "goto is considered harmful".
  7. I would use the Exit version and put the appending new record into its own method.
  8. FPiette

    Record Alignement and Delphi 10.4.1

    constructor TPdfObjectStream.Create(aDoc: TPdfDocument); begin inherited Create(aDoc,false); Attributes.AddItem('Type','ObjStm'); fAddingStream := TPdfWrite.Create(ADoc,THeapMemoryStream.Create); end; fObjectCount gets his random value from the inherited Create call. And in the inherite Create, fObjectCount gets his random value from the call to TPdfWrite.Create: constructor TPdfStream.Create(ADoc: TPdfDocument; DontAddToFXref: boolean=false); var FXref: TPdfXRef; begin inherited Create; if DontAddToFXref then FXRef := nil else begin FXRef := ADoc.FXref; FXRef.AddObject(self); end; FAttributes := TPdfDictionary.Create(FXref); FAttributes.AddItem('Length', TPdfNumber.Create(0)); if ADoc.CompressionMethod=cmFlateDecode then FFilter := 'FlateDecode'; FWriter := TPdfWrite.Create(ADoc,THeapMemoryStream.Create); end; I single stepped TPdfWrite.Create to find out where fObjectCount in the caller class is corrupted. It is not corrupted before reaching the end! It is corrupted after return. I then single stepped in the assembly language. Evrything is OK up to the return point in TPdfStream.Create. The corrupting line is the assignation to FWriter SynPdf.pas.4146: FWriter := TPdfWrite.Create(ADoc,THeapMemoryStream.Create); 006D8B57 B201 mov dl,$01 006D8B59 A188B66900 mov eax,[$0069b688] 006D8B5E E8AD06D3FF call TObject.Create 006D8B63 50 push eax 006D8B64 8BCF mov ecx,edi 006D8B66 B201 mov dl,$01 006D8B68 A180D66C00 mov eax,[$006cd680] 006D8B6D E83A1B0000 call TPdfWrite.Create 006D8B72 89431D mov [ebx+$1d],eax <=== This instruction corrupt fObjectCount The address in [EBX+$1D] is the same as the address given by the debugger for FWriter ($AC7CFED) BUT the address of fObjectCount if only one byte away ($AC7CFEF). It should be 4 bytes since FWriter is apointer and I compiled to code in 32bits. IMO it is the compiler which generate bad code.
  9. Thread split off from if Data.TryGetValue(aId, vNewData) then vNewData.DataName := aName; else begin vNewData := TDataRec.Create; vNewData.DataId := aId; vNewData.DataName := aName; Data.Add(aId, vNewData); end; @Stefan Glienke - What is the best container for random lookup access for records?
  10. The most common way do text-processing in Delphi is to load a file into a TStringList and then process the text line-by-line. Often you need to save the contents of the StringList back to the file. The TStringList is one of the most widely used RTL classes. However there are a number of limitations discussed below: a) No easy way to preserve line breaks on Load/Save TStringList does not make any effort to recognize the type of line breaks (LF, CR or CRLF) in the files it opens, let alone save that for use on saving. b) Information loss without any warning or any option for dealing with that. Internally TStringList uses unicode strings, but when you save its contents to a file using the default encoding (ANSI), this may result in information loss, without getting any warning or having any means for dealing with that. TEncoding.GetBytes also suffers from that. c) No easy way to determine whether a file you loaded into a TStringList contained a BOM When you load a file (LoadFromFile method), the encoding of the file is stored but not the information about whether the file contained a BOM or not. The WriteBOM property is only used when you save a file. d) Last but not least, no easy way of dealing with utf8 encoded files without a BOM The default text file format in Linux systems, in Visual Studio Code and other editors, as well as in languages such as python 3 is utf8 without BOM. Reading such files with TStringList is problematic and can result in errors, because it thinks such files are ANSI encoded. You could change the DefaultEncoding to utf8, but then you get errors when you read ansi files. No effort is made to detect whether a file without a BOM contains utf8 sequences. Overall, it is desirable that, when you load a file using LoadFromFile and then you save it using SavetoFile, the saved copy is identical to the original. I am attaching a general purpose TStringList descendent that deals with all the above issues in case anyone has a use for that. XStringList.pas
  11. DelphiUdIT

    Debugging x64 DLL (c++) and Delphi

    Reported, https://quality.embarcadero.com/browse/RSP-30893
  12. Yes. Though, in the case of multiple identifiers, it may make sense to wrap them in another record, if that suits your needs, eg: type TDataRecID = record ProjectID: Integer; // or wharever ID: integer; end; PDataRec = ^TDataRec TDataRec = record DataID: TDataRecID; DataName: string; end; var Data: TArray<TDataRec>; function FindRecord(const aID: TDataRecID): PDataRec; var i: Integer; begin Result := nil; for i := Low(Data) to High(Data) do begin if (Data[i].DataID.ProjectID = aID.ProjectID) and (Data[i].DataID.ID = aID.ID) then begin Result := @Data[i]; Exit; end; end; end; function AddRecord(const aID: TDataRecID): PDataRec; var vNewData: TDataRec; begin vNewData := Default(TDataRec); vNewData.DataID := aID; Data := Data + [vNewData]; Result := @Data[High(Data)]; end; function EnsureRecord(const aID: TDataRecID): PDataRec; begin Result := FindRecord(aID); if Result = nil then Result := AddRecord(aID); end; procedure SaveData1(const aID: TDataRecID; const aName: string); var pData: PDataRec; begin pData := EnsureRecord(aID); pData.DataName := aName; end; Otherwise, yes, you could just handle them individually: type PDataRec = ^TDataRec TDataRec = record DataID: Integer; DataName: string; ProjectID: Integer; // or whatever end; var Data: TArray<TDataRec>; function FindRecord(aProjectID, aID: TDataRecID): PDataRec; var i: Integer; begin Result := nil; for i := Low(Data) to High(Data) do begin if (Data[i].ProjectID = aProjectID) and (Data[i].DataID = aID) then begin Result := @Data[i]; Exit; end; end; end; function AddRecord(aProjectID, aID: Integer): PDataRec; var vNewData: TDataRec; begin vNewData := Default(TDataRec); vNewData.DataID := aID; vNewData.ProjectID := aProjectID; Data := Data + [vNewData]; Result := @Data[High(Data)]; end; function EnsureRecord(aProjectID, aID: Integer): PDataRec; begin Result := FindRecord(aProjectID, aID); if Result = nil then Result := AddRecord(aProjectID, aID); end; procedure SaveData1(aProjectID, aID: Integer; const aName: string); var pData: PDataRec; begin pData := EnsureRecord(aProjectID, aID); pData.DataName := aName; end;
  13. Dmitry Arefiev

    Firedac - Sqlite - DateTime field

    Most right way will be to create an issue at quality.embarcadero.com. And attach the DB file with the words explaining what you did. I would expect, dates were inserted using format not supported by FireDAC.
  14. Stefan Glienke

    Record Alignement and Delphi 10.4.1

    The offset in the code is correct but the binary layout of the classes are not - here is the dump of the memory layout from the defect: --- TPdfObject --- offset: 4 size: 1 FObjectType: TPdfObjectType offset: 5 size: 4 FObjectNumber: Integer offset: 9 size: 4 FGenerationNumber: Integer offset: 13 size: 1 FSaveAtTheEnd: Boolean --- TPdfStream --- offset: 14 size: 2 ---PADDING--- offset: 16 size: 4 FAttributes: TPdfDictionary offset: 20 size: 4 FSecondaryAttributes: TPdfDictionary offset: 24 size: 1 FDoNotEncrypt: Boolean offset: 25 size: 4 FFilter: AnsiString offset: 29 size: 4 FWriter: TPdfWrite --- TPdfObjectStream --- offset: 31 size: 4 fObjectCount: Integer offset: 35 size: 4 fAddingStream: TPdfWrite offset: 39 size: 4 fObject: :TPdfObjectStream.:2 offset: 43 size: 1 ---PADDING--- size: 48 So the [ebx+$1d] is correct ($1d = 29) - but the starting offset in TPdfObjectStream is wrong. With align Word it looks like this: --- TPdfObject --- offset: 4 size: 1 FObjectType: TPdfObjectType offset: 5 size: 1 ---PADDING--- offset: 6 size: 4 FObjectNumber: Integer offset: 10 size: 4 FGenerationNumber: Integer offset: 14 size: 1 FSaveAtTheEnd: Boolean --- TPdfStream --- offset: 15 size: 1 ---PADDING--- offset: 16 size: 4 FAttributes: TPdfDictionary offset: 20 size: 4 FSecondaryAttributes: TPdfDictionary offset: 24 size: 1 FDoNotEncrypt: Boolean offset: 25 size: 1 ---PADDING--- offset: 26 size: 4 FFilter: AnsiString offset: 30 size: 4 FWriter: TPdfWrite --- TPdfObjectStream --- offset: 34 size: 4 fObjectCount: Integer offset: 38 size: 4 fAddingStream: TPdfWrite offset: 42 size: 4 fObject: :TPdfObjectStream.:2 offset: 46 size: 2 ---PADDING--- size: 52
  15. David Heffernan

    Dynamic arrays and copying

    This issue is covered explicitly by the documentation: http://docwiki.embarcadero.com/RADStudio/Sydney/en/Structured_Types_(Delphi)#Dynamic_Arrays
  16. How to use open array parameters to handle array subranges: https://delphisorcery.blogspot.com/2020/09/open-array-parameters-and-subranges.html
  17. Stefan Glienke

    Open array parameters and subranges

    Ugh, nasty sh*t - can repro in earlier versions than 10.4 as well. The compiler trips over the type inference - need to write MergeSort<T>(...) I would guess it spirals down into some endless loop trying to infer whatever comes back from that tricked Slice call. Updated the blog post - thanks
  18. Mahdi Safsafi

    Open array parameters and subranges

    Very nice article Stefan and the way you used Slice to avoid the copy is amazing ! Speaking of bugs, I found two drawback related to using open array param: First, I already wrote on this forum a topic about unnamed type and rtti. Compiler do not generate rtti for an unnamed type ! this is easy to avoid with most types because all what you need to do is to declare the type : type x = xxx. But for open array type that's impossible because the syntax conflicts with dynamic array syntax ! So I suppose there is no official way to have a correct rtti for a function that uses open array param. Second, On my D10.3, the TArray<T> example caused an "IDE/Compiler not responding" issue that always ends up by IDE restart: I was able to isolate the line that causes the issue : MergeSort(Slice(TOpenArray<T>((@values[mid])^), len - mid)); // if I comment this line everything works great ! I tried with different build mode (debug,release) and on different project and the result is always the same
  19. Stefan Glienke

    DUNIT X memory leak checking

    https://bitbucket.org/shadow_cs/delphi-leakcheck/src/master/ scroll down to "DUnitX integration"
×