Recent

Author Topic: Segmentation fault  (Read 927 times)

Lauriet

  • New Member
  • *
  • Posts: 20
Segmentation fault
« on: March 15, 2025, 01:04:30 am »
Hi folks,
I have an issue that is beyond my pay grade!

In the init procedure of the main file, when i call GetScreenSize it proceeds thru the procedure OK...BUT
when it exits init, I get the Segmentation fault.
If I leave GetScreenSize out....all is well.???????   %)

Any clues ???



cdbc

  • Hero Member
  • *****
  • Posts: 2108
    • http://www.cdbc.dk
Re: Segmentation fault
« Reply #1 on: March 15, 2025, 08:16:36 am »
Hi
Methinks you need to debug this procedure:
Code: Pascal  [Select][+][-]
  1. procedure GetScreenSize;
  2. var
  3.   s       : Str16 = '';
  4.   NumRead : Integer;
  5.  
  6.  
  7.   function str2Int(txt : Str16) : Byte;
  8.   var
  9.     i, c : Byte;
  10.   begin
  11.     Val(txt, i, c);
  12.     if c = 0 then
  13.       str2Int := i
  14.     else
  15.       str2Int := 0;
  16.   end;
  17.  
  18. begin
  19.   ScreenSizeX := 0;
  20.   ScreenSizeY := 0;
  21.   write(#27'[18t'); {-- returns: \e[8;line;columnt (note the last 't')}
  22.  
  23.   s := '';
  24.   Repeat
  25.     NumRead := fpRead(StdInputHandle, S, 16);
  26.   until NumRead <> -1;
  27.  
  28.   Delete(s, 1, 3);
  29.   ScreenSizeY := str2Int(Copy(s, 1, Pos(';', S)-1));
  30.   Delete(S, 1, Pos(';', S));
  31.   ScreenSizeX := str2Int(Copy(s, 1, Pos('t', S)-1));
  32. end;
f.ex.:
- What happens if/when 'Str2Int' returns 0 in your calculations?!?
- I don't think any of the 'fpxx' functions will return -1, thus you'll have an
  endless loop on your hands...

You need to make sure this procedure functions properly and don't make any assumptions!
Regards Benny

edit: typo
« Last Edit: March 15, 2025, 08:19:49 am by cdbc »
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 3.6 up until Jan 2024 from then on it's both above &: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 4.99

Thaddy

  • Hero Member
  • *****
  • Posts: 16826
  • Ceterum censeo Trump esse delendam
Re: Segmentation fault
« Reply #2 on: March 15, 2025, 08:24:53 am »
Make screen size unsigned.....?
Anything that can not be negative should be unsigned.
(Like pointers?)

Makes such mistakes also much easier to debug.
« Last Edit: March 15, 2025, 08:27:18 am by Thaddy »
Changing servers. thaddy.com may be temporary unreachable but restored when the domain name transfer is done.

Lauriet

  • New Member
  • *
  • Posts: 20
Re: Segmentation fault
« Reply #3 on: March 16, 2025, 12:53:56 am »
Hi
Methinks you need to debug this procedure:
Code: Pascal  [Select][+][-]
  1. procedure GetScreenSize;
  2. var
  3.   s       : Str16 = '';
  4.   NumRead : Integer;
  5.  
  6.  
  7.   function str2Int(txt : Str16) : Byte;
  8.   var
  9.     i, c : Byte;
  10.   begin
  11.     Val(txt, i, c);
  12.     if c = 0 then
  13.       str2Int := i
  14.     else
  15.       str2Int := 0;
  16.   end;
  17.  
  18. begin
  19.   ScreenSizeX := 0;
  20.   ScreenSizeY := 0;
  21.   write(#27'[18t'); {-- returns: \e[8;line;columnt (note the last 't')}
  22.  
  23.   s := '';
  24.   Repeat
  25.     NumRead := fpRead(StdInputHandle, S, 16);
  26.   until NumRead <> -1;
  27.  
  28.   Delete(s, 1, 3);
  29.   ScreenSizeY := str2Int(Copy(s, 1, Pos(';', S)-1));
  30.   Delete(S, 1, Pos(';', S));
  31.   ScreenSizeX := str2Int(Copy(s, 1, Pos('t', S)-1));
  32. end;
f.ex.:
- What happens if/when 'Str2Int' returns 0 in your calculations?!?
- I don't think any of the 'fpxx' functions will return -1, thus you'll have an
  endless loop on your hands...

You need to make sure this procedure functions properly and don't make any assumptions!
Regards Benny

edit: typo

If Str2Int returns zero, then the screensizex and screensizey become zero. I don't see an endless loop ???

Lauriet

  • New Member
  • *
  • Posts: 20
Re: Segmentation fault
« Reply #4 on: March 16, 2025, 12:55:41 am »
If i step thru the procedure with the debugger, everything is working as expected.
It goes on to complete the other procedure calls in "Init" and only when it exits "init"
does the seg fault happen ???

jamie

  • Hero Member
  • *****
  • Posts: 6880
Re: Segmentation fault
« Reply #5 on: March 16, 2025, 01:53:59 am »
I see all kinds of issues that aren't clear.

For one, what is "Str16" ? is that a short string at a fixed length, double wide etc?

also, I see that you see it to '' at the start which makes it null and so on.

if you set the string to null at the start, its possible a new string will be created which will hold 0, and if that is the case, you overwrite memory.

the fpRead function, is that overloaded to handle strings and if so, what kind ?

The only true wisdom is knowing you know nothing

Lauriet

  • New Member
  • *
  • Posts: 20
Re: Segmentation fault
« Reply #6 on: March 16, 2025, 06:58:26 am »
Str16 is defined at the top of the unit as:
type
  Str16 = String[16];

A plain old fashion ordinary string.
As mentioned when I step thru the code of "GetScreenSize", diplayimg all the variables, everything is working.
 %)
« Last Edit: March 16, 2025, 07:03:01 am by Lauriet »

cdbc

  • Hero Member
  • *****
  • Posts: 2108
    • http://www.cdbc.dk
Re: Segmentation fault
« Reply #7 on: March 16, 2025, 07:21:05 am »
Hi
With a few changes, I got this to work:
Code: Pascal  [Select][+][-]
  1. type
  2.   Str16 = String[32]; /// <- HERE
  3. ...
  4. procedure GetScreenSize;
  5. var
  6.   s       : Str16 = '';
  7.   NumRead : ptrint; /// <- HERE
  8.  
  9.  
  10.   function str2Int(txt : Str16) : Byte;
  11.   var
  12.     i, c : Byte;
  13.   begin
  14.     Val(txt, i, c);
  15.     if c = 0 then
  16.       str2Int := i
  17.     else
  18.       str2Int := 0;
  19.   end;
  20.  
  21. begin
  22.   ScreenSizeX := 0;
  23.   ScreenSizeY := 0;
  24.   write(#27'[18t'); {-- returns: \e[8;line;columnt (note the last 't')}
  25.                     {              [8;31;98t?bB        ?? }            
  26.   s := '';
  27.   Repeat
  28.     NumRead := fpRead(StdInputHandle, S, 32); /// <- HERE
  29.   until NumRead > 0; /// <- HERE
  30.  
  31.   Delete(s, 1, 3);
  32.   ScreenSizeY := str2Int(Copy(s, 1, Pos(';', S)-1));
  33.   Delete(S, 1, Pos(';', S));
  34.   ScreenSizeX := str2Int(Copy(s, 1, Pos('t', S)-1));
  35. end;
Btw. all strings are shortstring, as the project compiles with mode fpc NOT objfpc!
...and when running it uses 1 core 100 % -> your main-loop could use a little breather here and there...
HTH
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 3.6 up until Jan 2024 from then on it's both above &: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 4.99

Lauriet

  • New Member
  • *
  • Posts: 20
Re: Segmentation fault
« Reply #8 on: March 16, 2025, 11:47:07 am »
Yep, it does work now.
In fact you don't need PtrInt, you can still use Byte;
I guess the buffer size of 32 is the key???
I don't know why, since the ascii return code is <16.

But wait !
What also works is defining s as array[1..16] of char and then assigning it to a string before doing the string manipulation.
So, I guess that all comes back to fpRead, not liking a String as a parameter ????

What also works is to leave out fpRead and use:

repeat
  Read(Ch);
  s := s + Ch;
until Ch = 't';



 
« Last Edit: March 16, 2025, 11:51:27 am by Lauriet »

cdbc

  • Hero Member
  • *****
  • Posts: 2108
    • http://www.cdbc.dk
Re: Segmentation fault
« Reply #9 on: March 16, 2025, 12:33:57 pm »
Hi
Good.
If you're doing stuff like this,
Quote
repeat
  Read(Ch);
  s := s + Ch;
until Ch = 't';

then here is some inspiration for you:
Code: Pascal  [Select][+][-]
  1. type
  2.   PTUiSize = ^TTUiSize;
  3.   TTUiSize = record
  4.     tsLines,
  5.     tsCols: byte; /// pretty decent, enough anyways
  6.   end;
  7. ...
  8.  
  9. function ParseScrSize(aStr: string): TTUiSize;
  10. type TState = (stNone,stLines,stCols,stDone);
  11. var len: word; state: TSTate; cst,lst: string;
  12.   P,pe: pchar;
  13. begin
  14.   len:= Length(aStr); Result.tsCols:= 0; Result.tsLines:= 0;
  15.   if len = 0 then exit;
  16.   P:= pchar(aStr); pe:= P + len; state:= stNone; cst:= ''; lst:= '';
  17.   while P <= pe do begin
  18.     case state of
  19.       stNone: if P^ = ';' then state:= stLines;
  20.       stLines: begin
  21.                  if P^ in ['0'..'9'] then lst+= P^;
  22.                  if P^ = ';' then state:= stCols;
  23.                end;
  24.       stCols: begin
  25.                 if P^ in ['0'..'9'] then cst+= P^;
  26.                 if P^ = 't' then state:= stDone;
  27.               end;
  28.       stDone: break; { exit stage left }
  29.     end;
  30.     inc(P);
  31.   end; /// while
  32.   Result.tsCols:= str2Int(cst);
  33.   Result.tsLines:= str2Int(lst);
  34. end;
Just inspiration, you need to change it to your use-case...
...Pick the values as you read them from stdinput...
Regards Benny
« Last Edit: March 16, 2025, 12:35:43 pm by cdbc »
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 3.6 up until Jan 2024 from then on it's both above &: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 4.99

Lauriet

  • New Member
  • *
  • Posts: 20
Re: Segmentation fault
« Reply #10 on: March 17, 2025, 01:32:56 am »
I guess fpRead puts the ansii string into S starting at char 0. The length byte, so the length would be set to
#27 as this is the first byte returned. That probably screws up the stack frame. Of course Pascal is strongly typed and I don't think its unreasonable to expect the compiler to flag an incompatible parameter(this is C's problem)
But I don't understand why it returned from "GetScreenSize" called a few more procedures, and only then faulted???

Curiously enough, the Read(Ch) approach only works in the ReadMouse procure IF the debugger is switch OFF.
If it is switched ON the fpRead approach works ????
« Last Edit: March 17, 2025, 02:57:20 am by Lauriet »

cdbc

  • Hero Member
  • *****
  • Posts: 2108
    • http://www.cdbc.dk
Re: Segmentation fault
« Reply #11 on: March 17, 2025, 07:24:34 am »
Hi
You could try:
Code: Pascal  [Select][+][-]
  1. NumRead := fpRead(StdInputHandle, S[1], 32);
Given this implementation of FpRead:
Code: Pascal  [Select][+][-]
  1. Function  FpRead           (fd : cInt;var buf; nbytes : TSize): TSsize; {$ifdef VER2_0}inline;{$endif}
  2.  
  3. begin
  4.   FPRead:=xFpRead(fd,PAnsiChar(@buf),nbytes);
  5. end;  
It should work just fine... EDIT: IT DOESN'T!!!
The old FpRead works just fine here...
Regards Benny
« Last Edit: March 17, 2025, 09:14:19 am by cdbc »
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 3.6 up until Jan 2024 from then on it's both above &: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 4.99

 

TinyPortal © 2005-2018