Recent

Author Topic: Same code works on x86, crashes on ARM  (Read 6144 times)

TCH

  • Full Member
  • ***
  • Posts: 124
Same code works on x86, crashes on ARM
« on: July 30, 2018, 11:28:12 pm »
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][+][-]
  1. unit bitfield;
  2.  
  3. interface
  4.  
  5. uses Classes, Forms, StdCtrls, Controls;
  6.  
  7. type
  8.         TBitSent = procedure (Sender: TObject; bit: Boolean; pos: Integer) of object;
  9.  
  10.         TBitfield = class(TEdit)
  11.                 private
  12.                         FBitWidth: word;
  13.                         FBitSent: TBitSent;
  14.                         procedure SetBitWidth(w: Word);
  15.                         procedure KeyPress(Sender: TObject; var Key: Char);
  16.                         procedure SetBits(q: QWord);
  17.                         function GetBits: QWord;
  18.                 public
  19.                         var ID: QWord;
  20.                         property Bits: QWord read GetBits write SetBits;
  21.                         property BitWidth: Word read FBitWidth write SetBitWidth;
  22.                         property OnBitSent: TBitSent read FBitSent write FBitSent;
  23.                         constructor Create(TheOwner: TComponent);
  24.                         destructor Destroy;
  25.         end;
  26.  
  27. implementation
  28.  
  29. procedure TBitfield.SetBitWidth(w: Word);
  30. var
  31.         i: Integer;
  32.         add: String;
  33. begin
  34.         if (w > 64) then exit;
  35.         if (w < Self.FBitWidth) then
  36.         begin
  37.                 Self.Text := Copy(Self.Text, 1, w);
  38.         end
  39.         else
  40.         begin
  41.                 if (w > Self.FBitWidth) then
  42.                 begin
  43.                         add := '';
  44.                         for i := 1 to (w - Self.FBitWidth) do
  45.                         begin
  46.                                 add := add + '0';
  47.                         end;
  48.                         Self.Text := add + Self.Text;
  49.                 end;
  50.         end;
  51.         Self.FBitWidth := w;
  52. end;
  53.  
  54. procedure TBitfield.KeyPress(Sender: TObject; var Key: Char);
  55. var
  56.         pos, bp: Integer;
  57.         cp: TPoint;
  58. begin
  59.         pos := (Self.CaretPos.X + 1);
  60.         if (pos > Self.FBitWidth) then exit;
  61.         if ((Key = #48) or (Key = #49)) then
  62.         begin
  63.                 bp := Self.FBitWidth - pos;
  64.                 if (Self.FBitSent <> nil) then Self.FBitSent(Sender, Key <> #48, bp);
  65.                 Self.Text := Copy(Self.Text, 1, Self.CaretPos.X) + Key + Copy(Self.Text, pos + 1, bp); // this line crashes on ARM
  66.                 cp.X := pos - 1;
  67.                 cp.Y := 0;
  68.                 Self.CaretPos := cp;
  69.         end;
  70. end;
  71.  
  72. procedure TBitfield.SetBits(q: QWord);
  73. var
  74.         i: QWord;
  75.         s: String;
  76. begin
  77.         s := '';
  78.         i := QWord(1) shl (Self.FBitWidth - 1);
  79.         while (i > 0) do
  80.         begin
  81.                 s := s + chr(48 + integer((q and i) <> 0));
  82.                 i := i shr 1;
  83.         end;
  84.         Self.Text := s;
  85. end;
  86.  
  87. function TBitfield.GetBits: QWord;
  88. var i, j: Integer;
  89. begin
  90.         Result := 0;
  91.         i := Self.FBitWidth - 1;
  92.         for j := 1 to Self.FBitWidth do
  93.         begin
  94.                 Result := Result or (integer(Self.Text[j] <> #48) shl i);
  95.                 i := i shr 1;
  96.         end;
  97. end;
  98.  
  99. constructor TBitfield.Create(TheOwner: TComponent);
  100. begin
  101.         inherited Create(TheOwner);
  102.         Self.ReadOnly := True;
  103.         Self.OnKeyPress := TKeyPressEvent(@(Self.KeyPress));
  104.         Self.Text := '';
  105. end;
  106.  
  107. destructor TBitfield.Destroy;
  108. begin
  109.         inherited Destroy;
  110. end;
  111.  
  112. end.
  113.  
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

  • Hero Member
  • *****
  • Posts: 3646
Re: Same code works on x86, crashes on ARM
« Reply #1 on: July 31, 2018, 12:22:25 am »
Code: Pascal  [Select][+][-]
  1. var  s: TCaption;
  2. begin
  3.   ...
  4.   s := Edit1.Text;
  5.   s[12] := 'a';
  6.   Edit1.Text := s;
  7.   ...
  8. end;
Of course if Length(Edit1.Text) is  shorter than 12 this will give you problems...

TCH

  • Full Member
  • ***
  • Posts: 124
Re: Same code works on x86, crashes on ARM
« Reply #2 on: July 31, 2018, 02:01:20 pm »
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?
« Last Edit: July 31, 2018, 02:35:49 pm by TCH »

Thaddy

  • Hero Member
  • *****
  • Posts: 10707
Re: Same code works on x86, crashes on ARM
« Reply #3 on: July 31, 2018, 03:18:31 pm »
What 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

  • Full Member
  • ***
  • Posts: 124
Re: Same code works on x86, crashes on ARM
« Reply #4 on: July 31, 2018, 06:53:36 pm »
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][+][-]
  1. kecske := TBitfield.Create(Form1);
  2. kecske.Parent := TWinControl(Form1);
  3. 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

  • Full Member
  • ***
  • Posts: 124
Re: Same code works on x86, crashes on ARM
« Reply #5 on: August 02, 2018, 07:22:33 pm »
It appears to me, you have lost the bet...

howardpc

  • Hero Member
  • *****
  • Posts: 3646
Re: Same code works on x86, crashes on ARM
« Reply #6 on: August 02, 2018, 07:41:28 pm »
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

  • Full Member
  • ***
  • Posts: 124
Re: Same code works on x86, crashes on ARM
« Reply #7 on: August 06, 2018, 10:47:33 am »
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

  • Hero Member
  • *****
  • Posts: 3646
Re: Same code works on x86, crashes on ARM
« Reply #8 on: August 06, 2018, 01:24:43 pm »
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

  • Hero Member
  • *****
  • Posts: 10707
Re: Same code works on x86, crashes on ARM
« Reply #9 on: August 06, 2018, 03:37:15 pm »
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.
« Last Edit: August 06, 2018, 03:45:19 pm by Thaddy »

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 6906
  • Debugger - SynEdit - and more
    • wiki
Re: Same code works on x86, crashes on ARM
« Reply #10 on: August 06, 2018, 03:39:27 pm »
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

  • Hero Member
  • *****
  • Posts: 10707
Re: Same code works on x86, crashes on ARM
« Reply #11 on: August 06, 2018, 03:48:08 pm »
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
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

  • Full Member
  • ***
  • Posts: 124
Re: Same code works on x86, crashes on ARM
« Reply #12 on: August 09, 2018, 07:05:34 pm »
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

  • Hero Member
  • *****
  • Posts: 10707
Re: Same code works on x86, crashes on ARM
« Reply #13 on: August 09, 2018, 07:56:17 pm »
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

  • Full Member
  • ***
  • Posts: 124
Re: Same code works on x86, crashes on ARM
« Reply #14 on: August 09, 2018, 08:05:04 pm »
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.

 

TinyPortal © 2005-2018