[SOLVED] Commit ee10850a of 17 Oct, 2021 breaks msegui compatibility. lazarus / 62-General ---------------------------------------------------------------------- Fred vS · 2021-10-27 13:57 Hello.     After high fight I found the commit that creates problems:     Commit ee10850a of 17 Oct, 2021: Reducing and aligning ...     https://gitlab.com/freepascal.org/fpc/source/- /commit/ee10850a5793b69b19dc82b9c28342bdd0018f2e     Since that commit all my applications do not run anymore.   This was the answer of Florian: QuoteWell, they probably make assumptions about internla structures they shouldn't: https://wiki.freepascal.org/User_Changes_Trunk#System_- _Ref._count_of_strings Hum, who are "they probably make assumptions"? The fpc committers or the libraries of my applications? I am lost and dont see where to look. Please and re-please would it be possible to do commits that does not break compatibility? If no, where to look, what to fix, the "User_Changed..." and his "how to fix" did not help. Thanks. Fre;D ---------------------------------------------------------------------- Bart · 2021-10-27 15:38 Quote from: Fred vS on October 27, 2021, 03:57:21 pmPlease and re- please would it be possible to do commits that does not break compatibility? Well, this is going to happen in trunk (or should I say main) every now and then. Bart ---------------------------------------------------------------------- Jonas Maebe · 2021-10-27 17:58 Quote from: Fred vS on October 27, 2021, 03:57:21 pmHum, who are "they probably make assumptions"? The fpc committers or the libraries of my applications? Your application probably makes an assumption about the internal layout of the header that precedes ansistrings (tansirec in the system unit, rtl/inc/astrings.inc). This record type is not exported via the interface of the system unit, which means code outside the compiler/RTL cannot rely on its layout or contents (except via public helpers such as System.StringRefCount, as mentioned on the User Changes page). ---------------------------------------------------------------------- Fred vS · 2021-10-28 13:37 Quote from: Jonas Maebe on October 27, 2021, 07:58:55 pmQuote from: Fred vS on October 27, 2021, 03:57:21 pmHum, who are "they probably make assumptions"? The fpc committers or the libraries of my applications? Your application probably makes an assumption about the internal layout of the header that precedes ansistrings (tansirec in the system unit, rtl/inc/astrings.inc). This record type is not exported via the interface of the system unit, which means code outside the compiler/RTL cannot rely on its layout or contents (except via public helpers such as System.StringRefCount, as mentioned on the User Changes page). Hello Jonas and thanks for answer. After lot of long hours of trying to fix, I have to stop, I cannot fix it. Quoteexcept via public helpers such as System.StringRefCountSadly StringRefCount works only for Tansistring and Tunicodestrings. But could it be possible to think to add condition in the problematic commit. After deep tests it appears that the problems occur with the patch done to rtl/inc/astrings.inc and /rtl/inc/ustrings  ( patch for compiler/aasmcnst.pas is OK. ) So the proposition is this, use a define to give the possibility to user to not use the patch: This is the problematic patch in rtl/inc/astrings.inc and /rtl/inc/ustrings : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$if not defined(VER3_0) and not defined(VER3_2)}  {$ifdef CPU64}            Ref         : Longint;  {$else}    Ref         : SizeInt;  {$endif}{$else}  {$ifdef CPU64}            { align fields  }        Dummy       : DWord;  {$endif CPU64}    Ref         : SizeInt;{$endif}  And replace by something like this (see no64bitRref): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$if (not defined(VER3_0)) and (not defined(VER3_2)) and (not defined(no64bitRref))} // here change  {$ifdef CPU64}            Ref       : Longint;  {$else}    Ref         : SizeInt;  {$endif}{$else}  {$ifdef CPU64}            { align fields  }        Dummy       : DWord;  {$endif CPU64}    Ref         : SizeInt;{$endif} With this, if somebody does not want the new feature, just add that parameter at compil : -dno64bitRref And so everybody is happy, even the people that uses libraries that dont like the original commit. Fre;D ---------------------------------------------------------------------- marcov · 2021-10-28 13:48 Quote from: Fred vS on October 28, 2021, 03:37:23 pmSo the proposition is this, use a define to give the possibility to user to not use the patch: This is not how it works. We can't cater to faulty code. If you can't fix it, you simply have to stay with older versions till you can fix the problem in your code. ---------------------------------------------------------------------- Fred vS · 2021-10-28 13:56 Quote from: marcov on October 28, 2021, 03:48:27 pmQuote from: Fred vS on October 28, 2021, 03:37:23 pmSo the proposition is this, use a define to give the possibility to user to not use the patch: This is not how it works. We can't cater to faulty code. If you can't fix it, you simply have to stay with older versions till you can fix the problem in your code. Yes but the problem is not only in my code but in code of other libraries too. ---------------------------------------------------------------------- Jonas Maebe · 2021-10-28 19:45 Quote from: Fred vS on October 28, 2021, 03:37:23 pmAfter deep tests it appears that the problems occur with the patch done to rtl/inc/astrings.inc and /rtl/inc/ustrings  ( patch for compiler/aasmcnst.pas is OK. ) If you revert the changes in the RTL, you also have to revert the compiler change. Otherwise the compiler will generate data for the new definition while the code in the RTL uses the old definition. ---------------------------------------------------------------------- PascalDragon · 2021-10-30 13:22 Quote from: Fred vS on October 28, 2021, 03:37:23 pmQuoteexcept via public helpers such as System.StringRefCountSadly StringRefCount works only for Tansistring and Tunicodestrings. First of they're named AnsiString and UnicodeString without any T-prefix and second these two types are the only two types that use the record so that StringRefCount only works with those two types is no problem. Quote from: Fred vS on October 28, 2021, 03:37:23 pmAnd so everybody is happy, even the people that uses libraries that dont like the original commit. No, that means that you can't use precompiled units from someone else and also - as Jonas pointed out - that you can even use the same compiler. This will be even more true once we support dynamic packages and officially ship libraries, because they will be precompiled as well. Quote from: Fred vS on October 28, 2021, 03:56:14 pmYes but the problem is not only in my code but in code of other libraries too. No, the problem is relying on undocumented implementation details. We don't give guarantees that implementation details stay the same, because these details might be because of some bug that needs to be fixed. ---------------------------------------------------------------------- Fred vS · 2021-10-30 14:42 Quote from: PascalDragon on October 30, 2021, 03:22:11 pmQuote from: Fred vS on October 28, 2021, 03:37:23 pmQuoteexcept via public helpers such as System.StringRefCountSadly StringRefCount works only for Tansistring and Tunicodestrings. First of they're named AnsiString and UnicodeString without any T-prefix and second these two types are the only two types that use the record so that StringRefCount only works with those two types is no problem. Hello Sven. Ok, but in comment they said: Quotepatch by Sergey Larin: Reducing and aligning the size of TAnsiRec, TUnicodeRec for CPU64 Quote from: PascalDragon on October 30, 2021, 03:22:11 pmQuote from: Fred vS on October 28, 2021, 03:56:14 pmYes but the problem is not only in my code but in code of other libraries too. No, the problem is relying on undocumented implementation details. We don't give guarantees that implementation details stay the same, because these details might be because of some bug that needs to be fixed. Sorry but I dont understand this "No, the problem is relying on undocumented implementation details.". What are the "implementation details", and what bug must be fixed ? Do you want to say that there was bug in the libraries used before the commit ee10850a? Strange because all was functioning perfectly before that commit. Now about how to fix the bug after the commit ee10850a. I did spent some (many) time to fix it but without luck. Does somebody have a idea what could affect that difference in the reference counter of AnsiString and UnicodeString ? What method will have impact on that change and what must be changed? Thanks. Fre;D ---------------------------------------------------------------------- Jonas Maebe · 2021-10-30 15:34 Quote from: Fred vS on October 30, 2021, 04:42:53 pmDoes somebody have a idea what could affect that difference in the reference counter of AnsiString and UnicodeString ? The reason nobody really has any idea about this or can't tell you this, is because this change cannot affect any code that uses ansistrings/unicodestrings "normally": concatenating, passing as parameters, returning as function result, using them as a pchar, converting them to other string types, ... It can only cause problems if MSE somewhere e.g. typecasts an ansistring or unicodestring to a pointer, and then uses pointer arithmetic to manually calculate what it thinks is the offset of the reference count (or another field whose offset changed). That's also why we say this change can only break code that relies on an implementation detail. There was/is no guarantee about how the header that sits in front of an ansistring or unicodestring looks like, which is also the reason why it could be changed. ---------------------------------------------------------------------- Fred vS · 2021-10-30 15:53 Quote from: Jonas Maebe on October 30, 2021, 05:34:22 pmQuote from: Fred vS on October 30, 2021, 04:42:53 pmDoes somebody have a idea what could affect that difference in the reference counter of AnsiString and UnicodeString ? It can only cause problems if MSE somewhere e.g. typecasts an ansistring or unicodestring to a pointer, and then uses pointer arithmetic to manually calculate what it thinks is the offset of the reference count (or another field whose offset changed). Hello Jonas. Many thanks for that precious infos. Yes, this is exactly the problem that I wanted to explain. And it is exactly what I dont find: where, in MSE code, they typecast an ansistring or unicodestring to a pointer wrongly. Anyway, I know now precisely where to look (again). Thanks for helping. Fre;D ---------------------------------------------------------------------- Martin_fr · 2021-10-30 16:26 Your code probably casts an (ansi-)string to a pointer, and accesses memory in front of the pointer. Something like: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   if PLongInt(MySomeString)[-1] = 0 then Such code assumes that it finds the length or refcount or codepage of the string at the address accessed by the expression. But, the length/refcnt/codepage is no longer there. It was just random coincidence that it used to be there. It's called "implementation detail", and it can always change with no warning at all. ---------------------------------------------------------------------- FPK · 2021-10-30 17:37 I suppose Martin would have appreciated this change as it reduces memory usage and efficiency with little to no drawback. ---------------------------------------------------------------------- Roland57 · 2021-10-31 06:35 Quote from: Martin_fr on October 30, 2021, 06:26:47 pmYour code probably casts an (ansi-)string to a pointer, and accesses memory in front of the pointer. Something like: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   if PLongInt(MySomeString)[-1] = 0 then Such code assumes that it finds the length or refcount or codepage of the string at the address accessed by the expression. For example this procedure (in kernel/msestrings.pas)? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure stringaddref(var str: ansistring);var po1: psizeint;begin if pointer(str) <> nil then begin  po1:= pointer(str)-2*sizeof(sizeint);  if po1^ >= 0 then begin   inc(po1^);  end; end;end; ---------------------------------------------------------------------- Jonas Maebe · 2021-10-31 07:50 Quote from: Roland57 on October 31, 2021, 07:35:14 amFor example this procedure (in kernel/msestrings.pas)? Yes, absolutely. Here's an alternative way to implement that hack. It's still quite iffy, but at least a bit safer, and compatible both with old and new FPC versions: Code: [Select]    procedure stringaddref(var str: ansistring);     var      temp: ansistring;     begin      { increase refcount if it was > 0}      temp:=str;      { prevent the compiler from finalising temp, so it won't decrease the refcount again }      pointer(temp):=nil;     end; ---------------------------------------------------------------------- Martin_fr · 2021-10-31 10:27 Quote from: Roland57 on October 31, 2021, 07:35:14 amFor example this procedure (in kernel/msestrings.pas)? Exactly that. Additionally the "stringaddref" is not thread safe. Jonas' method is (to the point that any strings is thread save). ---------------------------------------------------------------------- Fred vS · 2021-10-31 14:39 Hello Roland, Florian, Jonas and Martin. Many thanks to help so much! OK, I did change procedure stringaddref(var str: ansistring) and procedure stringaddref(var str: msestring) with Jonas code. Note that I did already try, before your post, with this but it crash without any info from debugger: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure stringaddref(var str: ansistring);var po1: int64;begin if pointer(str) <> nil then begin po1:= StringRefCount(str);   if po1 >= 0 then begin   inc(po1);  end; end;end; The excellent news is that with Jonas procedure, it crash with note from the debugger. The debugger message: QuoteSignal: SIGSEGV: File msestrings.pas:878 Function: DOSTRINGTOUTF8 Here the code pointing to error: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure dostringtoutf8(const value: pmsechar;                                   var count: integer; const dest: pointer;                                                 const options: utfoptionsty);var ps,pe: pcard16; pd: pcard8; ca1: card16;...begin pd:= dest; ps:= pointer(value); pe:= ps + count; while ps < pe do begin  ca1:= ps^;    // Debugger point to this... [EDIT] Tried with changing this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var ps,pe: pcard32; // here change to card32 pd: pcard8; ca1: card32; // here change to card32 But still crash and now without any debugger help message, only this: QuoteAn unhandled exception occurred at $000000000060E501 : ?????????????????????? ... (+ much other chars) [Inferior 1 (process 8215) exited with code 0331] Hum, any idea what is wrong there? There is also that code that surely needs change (but with what?) : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure stringsafefree(var str: string; const onlyifunique: boolean);varpo1: psizeint;begin if pointer(str) <> nil then begin po1:= pointer(str)-2*sizeof(sizeint);   if (po1 >= 0) and (not onlyifunique or (po1 = 1)) then begin    fillchar(pointer(str)^,length(str)*sizeof(str[1]),0);   str:= '';  end; end;end; Thanks. Fre;D ---------------------------------------------------------------------- Jonas Maebe · 2021-10-31 17:11 Quote from: Fred vS on October 31, 2021, 03:39:16 pmNote that I did already try, before your post, with this but it crash without any info from debugger: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure stringaddref(var str: ansistring);var po1: int64;begin if pointer(str) <> nil then begin po1:= StringRefCount(str);   if po1 >= 0 then begin   inc(po1);  end; end;end; This version of that routine does nothing at all, because you just increase the value local variable. QuoteThe excellent news is that with Jonas procedure, it crash with note from the debugger. The debugger message: QuoteSignal: SIGSEGV: File msestrings.pas:878 Function: DOSTRINGTOUTF8 Here the code pointing to error: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure dostringtoutf8(const value: pmsechar;                                   var count: integer; const dest: pointer;                                                 const options: utfoptionsty);var ps,pe: pcard16; pd: pcard8; ca1: card16;...begin pd:= dest; ps:= pointer(value); pe:= ps + count; while ps < pe do begin  ca1:= ps^;    // Debugger point to this...This code is fine. It probably crashes here because it's working on an invalid string. Quote[EDIT] Tried with changing this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var ps,pe: pcard32; // here change to card32 pd: pcard8; ca1: card32; // here change to card32Don't start changing the types of random variables used during string processing. Analyse what needs changing, then change. QuoteThere is also that code that surely needs change (but with what?) : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure stringsafefree(var str: string; const onlyifunique: boolean);varpo1: psizeint;begin if pointer(str) <> nil then begin po1:= pointer(str)-2*sizeof(sizeint);   if (po1 >= 0) and (not onlyifunique or (po1 = 1)) then begin    fillchar(pointer(str)^,length(str)*sizeof(str[1]),0);   str:= '';  end; end;end;Here you can change the assignment of po1 with StringRefCount(str). ---------------------------------------------------------------------- Fred vS · 2021-10-31 19:21 Hello Jonas. You are the Champion. 1) QuoteThis code is fine. It probably crashes here because it's working on an invalid string. Indeed, my (lot of) attempts did corrupt the ini-status file. Fixed. 2) QuoteHere you can change the assignment of po1 with StringRefCount(str). Changed with this for string and msestring: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure stringsafefree(var str: string; const onlyifunique: boolean);var //po1: psizeint; po1: longint;begin if pointer(str) <> nil then begin // po1:= pointer(str)-2*sizeof(sizeint); po1:= StringRefCount(str); //  if (po1^ >= 0) and (not onlyifunique or (po1^ = 1)) then begin  if (po1 >= 0) and (not onlyifunique or (po1 = 1)) then begin   fillchar(pointer(str)^,length(str)*sizeof(str[1]),0);   str:= '';  end; end;end; 3)   Using your previous code for stringaddref for ansistring and msestring: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  procedure stringaddref(var str: ansistring);    var     temp: ansistring;    begin     { increase refcount if it was > 0}     temp:=str;     { prevent the compiler from finalising temp, so it won't decrease the refcount again }     pointer(temp):=nil;    end; 4)  Compile + run = Yep it run + loads + all seems to work (not yet tested deeply).   (see picture) There is still a problem when closing the app, the debugger point to this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function countchars(const str: msestring; achar: msechar): integer;var int1: integer;begin result:= 0; for int1:= 1 to length(str) do begin  if str[int1] = achar then begin // here debugger point   inc(result);  end; end;end; Sure we will find the solution. Anyway, many thanks for your help Jonas, MSEgui is still on the road, hand in hand with FPC ( and part of you is in MSE code now  ). PS: I fear that the same should be done for ZeosLib. Fre;D [EDIT] After some test, there are still problems but it is on the good way... ---------------------------------------------------------------------- Fred vS · 2021-10-31 21:51 Re-hello. Oooops, this: Quote3)   Using your previous code for stringaddref for ansistring and msestring:      Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure stringaddref(var str: ansistring);        var         temp: ansistring;        begin         { increase refcount if it was > 0}       temp:=str;         { prevent the compiler from finalising temp, so it won't decrease the refcount again }         pointer(temp):=nil;        end;  temp: ansistring, must of course be changed in procedure stringaddref(var str: msestring) with temp: msestring. Bad me, it was using temp: ansistring. Ok, changed this. Then compiles + runs = PERFECT, no crash at loading, no error at closing, even complicated app like StrumPract compilles + run perfectly with fpc 3.3.1 last trunk. OK, problem completely solved. Many thanks to you all particularity for Jonas and his perfect solution. Yep, Martin would be very happy (and I am very happy too).  [EDIT] : https://github.com/mse-org/mseide- msegui/commit/a069f4a1d9dc6a75a0f140b42ac7dca0adc8ac68 ---------------------------------------------------------------------- Roland57 · 2021-10-31 23:42 @Jonas, Martin Thank you for your help. I wonder if there won't be an issue also with this (still in msestrings.pas): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  stringheaderty = packed record{$ifdef hascodepage}  CodePage: TSystemCodePage;  ElementSize: Word; {$ifdef CPU64}    { align fields  }  Dummy: DWord; {$endif CPU64}{$endif}  ref: sizeint;  len: sizeint; end; I will look at it closer tomorrow. ---------------------------------------------------------------------- Fred vS · 2021-11-01 17:07 Quote from: Roland57 on November 01, 2021, 12:42:34 am@Jonas, Martin Thank you for your help. I wonder if there won't be an issue also with this (still in msestrings.pas): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  stringheaderty = packed record{$ifdef hascodepage}  CodePage: TSystemCodePage;  ElementSize: Word; {$ifdef CPU64}    { align fields  }  Dummy: DWord; {$endif CPU64}{$endif}  ref: sizeint;  len: sizeint; end; I will look at it closer tomorrow. Hello Roland. If I understood well, that code should not make conflict with some fpc because stringheaderty is not defined in fpc. But that code does not profit of the ee10850a commit from fpc that remove the "Dummy" element in 64 bit, nor do better alignment. If this is correct, imho it would be good to adapt the mse stringheaderty code and do the same as TAnsiRec, TUnicodeRec in ee10850a fpc commit. Fre;D ---------------------------------------------------------------------- PascalDragon · 2021-11-02 13:03 Quote from: Fred vS on November 01, 2021, 06:07:43 pmIf I understood well, that code should not make conflict with some fpc because stringheaderty is not defined in fpc. But that code does not profit of the ee10850a commit from fpc that remove the "Dummy" element in 64 bit, nor do better alignment. There won't be a type conflict, yes, but any code that uses stringheaderty will access wrong data on 64-bit, because the only use of tstringheaderty is to interact with the header record of Ansi- and UnicodeString which now have a mismatching memory layout. Quote from: Fred vS on November 01, 2021, 06:07:43 pmIf this is correct, imho it would be good to adapt the mse stringheaderty code and do the same as TAnsiRec, TUnicodeRec in ee10850a fpc commit. It would not only be good, but also correct to adjust the code. Better yet: check whether you can drop it. ---------------------------------------------------------------------- Fred vS · 2021-11-02 14:43 Quote from: PascalDragon on November 02, 2021, 02:03:58 pmQuote from: Fred vS on November 01, 2021, 06:07:43 pmIf I understood well, that code should not make conflict with some fpc because stringheaderty is not defined in fpc. But that code does not profit of the ee10850a commit from fpc that remove the "Dummy" element in 64 bit, nor do better alignment. There won't be a type conflict, yes, but any code that uses stringheaderty will access wrong data on 64-bit, because the only use of tstringheaderty is to interact with the header record of Ansi- and UnicodeString which now have a mismatching memory layout. Quote from: Fred vS on November 01, 2021, 06:07:43 pmIf this is correct, imho it would be good to adapt the mse stringheaderty code and do the same as TAnsiRec, TUnicodeRec in ee10850a fpc commit. It would not only be good, but also correct to adjust the code. Better yet: check whether you can drop it. Hello Sven. Thanks for that very clear explanation. Last question before I become Guru es AnsiString and UnicodeString. About the patch of Sergey Larin, why does it comes now ? It seems so evident in a 64 bit OS to use a longint vs sizeint and that "Dummy" element added is so strange. Was something changed in fpc code that makes that patch possible? Or is it Sergey Larin who discovers just last week that something was strange in AnsiString and UnicodeString in 64 bit Linux OS? Anyway, many thanks for your patch Sergey, now that it works for msegui I like it so much.  Have a perfect day. Fre;D ---------------------------------------------------------------------- Fred vS · 2021-11-02 17:40 Quote from: PascalDragon on November 02, 2021, 02:03:58 pmBetter yet: check whether you can drop it. Hum, yes we know and I agree.  To maintain msegui on the road bridge to fpc are needed. Circular did a class-bridge for all graphic things, now you may chose to use the build-in msegui graphic class vs those of fpc/BGRABitmap (or use both). For all file-access things, msegui uses now exclusively the fpc offer, it was too complicated to update the build-in msegui file access for each OS and till now no one of the msegui maintainers has the skill of Martin to do it. Also all the units used in /fpccompatibility/ that had the same name as those from fpc were renamed mse_xxx (and all msegui code adapted for this) to avoid possible conflict. Since this topic, for msestrings, it will be the same, loose some independence and use the fpc offer. Personally I am ok with this (and dont see other way to keep msegui in the race). Fre;D ---------------------------------------------------------------------- Roland57 · 2021-11-03 06:39 Quote from: PascalDragon on November 02, 2021, 02:03:58 pmIt would not only be good, but also correct to adjust the code. Better yet: check whether you can drop it. Thank you for your advice. stringheaderty is used in the tmemorystringstream class, declared in kernel/msestrings.pas. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type tmemorystringstream = class(tmemorystream)         //has room for stringheader Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i { tmemorystringstream }const stringheadersize = sizeof(stringheaderty); That class is used in some db units: [roland@localhost common]$ grep -Rni tmemorystringstream kernel/msestrings.pas:170: tmemorystringstream = class(tmemorystream) kernel/msestrings.pas:6164:{ tmemorystringstream } kernel/msestrings.pas:6168:constructor tmemorystringstream.create; kernel/msestrings.pas:6179:procedure tmemorystringstream.SetCapacity(NewCapacity: PtrInt); kernel/msestrings.pas:6184:function tmemorystringstream.getcapacity: ptrint; kernel/msestrings.pas:6189:function tmemorystringstream.Seek(const Offset: Int64; kernel/msestrings.pas:6204:function tmemorystringstream.getmemory: pointer; kernel/msestrings.pas:6209:function tmemorystringstream.GetSize: Int64; kernel/msestrings.pas:6214:function tmemorystringstream.GetPosition: Int64; kernel/msestrings.pas:6219:procedure tmemorystringstream.SetSize( kernel/msestrings.pas:6225:procedure tmemorystringstream.destroyasstring(out data: string); db/mibconnection.pas:1481:  result:= tmemorystringstream.create; db/mibconnection.pas:1505: tmemorystringstream(getblobstream(acursor,b lobid,true)).destroyasstring(result); db/msefb3connection.pas:1615:   result:= tmemorystringstream.create; db/msefb3connection.pas:1641: tmemorystringstream(getblobstream(acurso r,blobid,true)).destroyasstring(result); [roland@localhost common]$ Unfortunately I have no knowledge about databases. I don't know if there is a working demo project for these units. I would like to see clear in that question of string headers. For now I don't see what we could use instead of stringheaderty. It would be good to have little code examples. Is there a tutorial somewhere about that topic?