Same code works on x86, crashes on ARM lazarus / 62-General ---------------------------------------------------------------------- TCH · 2018-07-30 21:28 I have a small extension on TEdit, which works on x86, but on ARM a certain part crashes (namely line 65). Here is the code: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 unit bitfield; interface uses Classes, Forms, StdCtrls, Controls; type      TBitSent = procedure (Sender: TObject; bit: Boolean; pos: Integer) of object;         TBitfield = class(TEdit)                private                      FBitWidth: word;                        FBitSent: TBitSent;                        procedure SetBitWidth(w: Word);                      procedure KeyPress(Sender: TObject; var Key: Char);                      procedure SetBits(q: QWord);                      function GetBits: QWord;                public                      var ID: QWord;                        property Bits: QWord read GetBits write SetBits;                        property BitWidth: Word read FBitWidth write SetBitWidth;                        property OnBitSent: TBitSent read FBitSent write FBitSent;                      constructor Create(TheOwner: TComponent);                        destructor Destroy;        end; implementation procedure TBitfield.SetBitWidth(w: Word);var        i: Integer;        add: String;begin        if (w > 64) then exit;        if (w < Self.FBitWidth) then        begin                Self.Text := Copy(Self.Text, 1, w);        end        else        begin              if (w > Self.FBitWidth) then                begin                      add := '';                        for i := 1 to (w - Self.FBitWidth) do                        begin                              add := add + '0';                        end;                      Self.Text := add + Self.Text;                end;        end;      Self.FBitWidth := w;end; procedure TBitfield.KeyPress(Sender: TObject; var Key: Char);var        pos, bp: Integer;        cp: TPoint;begin        pos := (Self.CaretPos.X + 1);        if (pos > Self.FBitWidth) then exit;        if ((Key = #48) or (Key = #49)) then        begin                bp := Self.FBitWidth - pos;              if (Self.FBitSent <> nil) then Self.FBitSent(Sender, Key <> #48, bp);                Self.Text := Copy(Self.Text, 1, Self.CaretPos.X) + Key + Copy(Self.Text, pos + 1, bp); // this line crashes on ARM              cp.X := pos - 1;                cp.Y := 0;                Self.CaretPos := cp;        end;end; procedure TBitfield.SetBits(q: QWord);var        i: QWord;        s: String;begin        s := '';      i := QWord(1) shl (Self.FBitWidth - 1);        while (i > 0) do      begin                s := s + chr(48 + integer((q and i) <> 0));              i := i shr 1;        end;        Self.Text := s;end; function TBitfield.GetBits: QWord;var i, j: Integer;begin      Result := 0;        i := Self.FBitWidth - 1;        for j := 1 to Self.FBitWidth do        begin                Result := Result or (integer(Self.Text[j] <> #48) shl i);                i := i shr 1;      end;end; constructor TBitfield.Create(TheOwner: TComponent);begin      inherited Create(TheOwner);        Self.ReadOnly := True;        Self.OnKeyPress := TKeyPressEvent(@(Self.KeyPress));        Self.Text := '';end; destructor TBitfield.Destroy;begin        inherited Destroy;end; end. I've debugged it, it's not one of the Copy commands, if i put the result in a separate string, then it's works. It's the Self.Text := whatever; which crashes. But only in that function, all other assigns works. Is it because it's in a key press handling event? But the TEdit is read only, so no concurrent write would occur. And also, the corresponding line does not crashes on x86. Any idea about this? Also, does anybody know how can i replace a single character in a TEdit.Text? TEdit.Text[12] := 'a'; is not allowed... ---------------------------------------------------------------------- howardpc · 2018-07-30 22:22 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  s: TCaption;begin  ...  s := Edit1.Text;  s[12] := 'a';  Edit1.Text := s;  ...end;Of course if Length(Edit1.Text) is  shorter than 12 this will give you problems... ---------------------------------------------------------------------- TCH · 2018-07-31 12:01 What happens in the background if i do this? It will only reassign the pointer and then do the replace? Won't it copy the entire string two times? Edit: I've checked the assembly and it does copy the entire string two times. The original just copied the two parts. How can i obtain the real memory address of the text data of a TEdit? ---------------------------------------------------------------------- Thaddy · 2018-07-31 13:18 Quote from: TCH on July 31, 2018, 02:01:20 pmWhat happens in the background if i do this? Nothing. Your code is likely wrong as Howard pointed out. Post a complete crashing example and I'll bet you it will be solved in seconds.... ---------------------------------------------------------------------- TCH · 2018-07-31 16:53 Howard gave a suggestion how to change one character, he did not pointed out about the code being wrong. If you mean the [12] offset, that was just an example, the crashing line is in the 65. line. But here it is: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 kecske := TBitfield.Create(Form1);kecske.Parent := TWinControl(Form1);kecske.BitWidth := 32;And then if i press 1 or 0 in the box, then on x86, it works, on ARM it's chrashes. ---------------------------------------------------------------------- TCH · 2018-08-02 17:22 It appears to me, you have lost the bet... ---------------------------------------------------------------------- howardpc · 2018-08-02 17:41 I think Thaddy was asking you to post a complete compilable project (.lpi, .pas, .lpr, .lfm only). It is usually impossible to properly debug a program only on the basis of a few code snippets taken from the presumed offending lines. The location of a crash may not pinpoint the source of the bug(s), it may simply be the end of a longer trail. ---------------------------------------------------------------------- TCH · 2018-08-06 08:47 The complete project is a simple, freshly created Lazarus Application with everything default and with the unit in the starter post and the previous three lines in TForm.Create. Nothing else. ---------------------------------------------------------------------- howardpc · 2018-08-06 11:24 Perhaps the implementation of TEdit on your ARM platform does not permit changes to TEdit.Text (via code) when ReadOnly is True? Easily tested by setting ReadOnly to False. ---------------------------------------------------------------------- Thaddy · 2018-08-06 13:37 Windows: just blocks input devices, including clipboard, but allows setting/changing content from code. (Windows quirk, bug) Other widgetsets: read-only is read-only after initial content is set. Won't change anything not even from code. For arm, claim the control, make it temporary read/write and set back to readonly when done. ---------------------------------------------------------------------- Martin_fr · 2018-08-06 13:39 What options to compile to you use? Have you tried to compile with -O-0 (no optimization), and all range and other checks enabled? -gh -Criot -gt ---------------------------------------------------------------------- Thaddy · 2018-08-06 13:48 Quote from: Martin_fr on August 06, 2018, 03:39:27 pmWhat options to compile to you use? Have you tried to compile with -O-0 (no optimization), and all range and other checks enabled? -gh -Criot -gt That does not matter: a Windows control is read-only for input devices only. So it allows code to change it. The other widget sets seem to be more strict: claim it, set to read write, change content and subsequently set to read-only again. It is not related to optimization levels. ---------------------------------------------------------------------- TCH · 2018-08-09 17:05 I tried to switch ReadOnly on and off, but did not helped. However, it turned out, that it's does an access violation in cases, but i cannot figure it out. But it always does it on that line. Here is the full source: http://oscomp.hu/depot/el_gpiot.zip Currently there is a heatwave in Hungary and i'm suffering from thyroid issues, so i most probably did some lame error. I will appreciate if somebody pinpoints it... ---------------------------------------------------------------------- Thaddy · 2018-08-09 17:56 line 161 you mean? I suspect a rights issue. Try first to run the program as root. If that works we are close and I can write instructions to address the rights issue in a more reasonable fashion. ---------------------------------------------------------------------- TCH · 2018-08-09 18:05 No, on line 64. in "bitfield.pas", it always crashes on that line: Self.Text := Copy(Self.Text, 1, Self.CaretPos.X) + Key + Copy(Self.Text, pos + 1, bp); I always use my machines as root. ---------------------------------------------------------------------- Thaddy · 2018-08-09 18:16 When I run the program compiled with FPC trunk and Lazarus trunk as sudo, at least my Raspberry Pi 3 shows up correct. I made two small changes: - I call Form1.BeginFormUpdate/Form1.EndFormUpdate in the init button to speed up painting. - I changed the ridiculous try except to set the timer interval to 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   i := strtointdef(Edit1.Text,10);  So the program works OK. See screenshot. I saw more coding and layout issues, but those are for later. It works. Can be that you need to upgrade to trunk versions. ---------------------------------------------------------------------- TCH · 2018-08-09 19:08 No, you got it all wrong. As i told, the program crashes when you enter into the boxes and hit 1 or 0. Your changes are totally irrelevant to that. The program still crashes when editing the fields. And the problem is, that it works for the first N time, then suddenly it crashesh. If i change which TEdit i edit, then it crashes more easily. Still, thanks for the strtointdef function, i wasn't aware of that function. ---------------------------------------------------------------------- Thaddy · 2018-08-09 19:36 As long as I run as sudo I can also repeatedly edit the edit boxes and it does not crash.(yet) but I use fpc3.1.1 + Lazarus 1.9. What are you using? fpc version? Laz version? I forgot that I also added cthreads, btw. ---------------------------------------------------------------------- Thaddy · 2018-08-10 04:30 It still doesn't crash.... ---------------------------------------------------------------------- TCH · 2018-08-10 12:43 I am running it as a root. FPC is 3.0.2 and Lazarus is 1.6.4. It already had CThreads, as the relevant conditional macro has been commented out. Please send me the binary you built and let me try it. If it does not crash, then the problem is inside the version of Lazarus/FPC i use. If it crash, then it's in my system. ---------------------------------------------------------------------- Thaddy · 2018-08-10 13:33 Quote from: TCH on August 10, 2018, 02:43:54 pmI am running it as a root. FPC is 3.0.2 and Lazarus is 1.6.4. It already had CThreads, as the relevant conditional macro has been commented out. Please send me the binary you built and let me try it. If it does not crash, then the problem is inside the version of Lazarus/FPC i use. If it crash, then it's in my system. Ok. But you are using OLD versions and that's the cause! I will put it on my website, too large to attach. Link to binary is: http://thaddy.org/el_gpiot.zip compiled on RPi3 Rasbian-stretch. -O2 optimization. It works. But note it is compiled with trunk. I suppose 3.0.4 and 1.8.4 will also do (but not old crap) ---------------------------------------------------------------------- TCH · 2018-08-13 11:36 I have downloaded your binary and it crashes when i click on the Init button. It does not even get that far to show up the textfields... Is there any repository for Debian armv7l with Lazarus 1.8 and FPC 3.0.4? Debian repo contains only old ones and Lazarus download page does not have any ARM download. ---------------------------------------------------------------------- Thaddy · 2018-08-13 12:12 Well. I thoroughly tested it and here it does not crash. It only crashes if you are not running as root or sudo. Maybe a dependency is missing on your computer? Or a raspi-config setting? To obtain version 3.0.4 there are three options: 1. add stretch-backports to /etc/apt/sources.list. FPC 3.0.4 and Lazarus 1.8.4. are both in stretch-backports. You can subsequently install them with apt or apt-get     You need to install with the -t option. See https://backports.debian.org/Instructions/ 2. use fpcdeluxe 3. build from source. Here's how I do that. step 0. sudo apt-get update && sudo apt-get dist-upgrade -y If you haven't done that for a long time. step 1. check out the sources for fixes-3.0.4 or 3.1.1 trunk for fpc from svn step 2. rename or copy the executable (not the symlink ) ppcarm to fpcstart and move it to your home directory.            If /usr/local/bin/ppcarm is a symlink, the binary is here: /usr/local/lib/fpc/3.0.2/ppcarm or here /usr/lib/fpc/3.0.2/ppcarm step 3. sudo apt-get remove fpc step 4. change to the directory where you checked out the sources, probably /home/pi/fpc step 5. sudo make clean all install  PP=/home/pi/fpcstart step 6. sudo cp /usr/local/lib/fpc/3.0.4/ppcarm /usr/local/bin. use 3.1.1 instead of 3.0.4. if you use trunk. step 7. type fpc -v in a terminal window. It should give you the new version. step 8. sudo apt-get remove lazarus step 9. check out the lazarus sources from git either 1.8.4 or trunk step 10. goto the lazarus source directory step 11. make clean all install step 12. type ./startlazarus ---------------------------------------------------------------------- Thaddy · 2018-08-13 13:55 @TCH I reworked the code a bit and it seems a bit more stable (I could intermittently get an error, seldom, but still...After all...). I suspect that the runtime control creation had issues. I will attach the code here later. [edit] Attached. ---------------------------------------------------------------------- Thaddy · 2018-08-13 19:54 @TCH Currently solving some issues regarding you not testing fpopen, fpclose, fpmmap and fpmunmap results. I have introduced a EGpioException to handle those and made the procedures in el_gpiot into boolean functions. Will attach code tomorrow. We're getting there. I also made everything range safe: it wasn't. ---------------------------------------------------------------------- Jonny · 2021-01-10 19:10 Sorry for reviving an old thread. Was el_gpiot ever updated? It compiles with trunk but GPIO's do not respond on my RPi3b.