2

I have a string with a word at the begining (that I want to ignore) and then some numbers that I want to store in an array. Not all of them, just some.

I use sscanf like this

var
    x: integer;
    y: array[0..19] of integer;
    s: pchar;
begin
    ...
    sscanf(dataline, "%s %d %d %d %d %d %d %d %d %d %d %d",
            [s, @x, @y[0], @y[1], @y[2], @y[3], @y[4],
                    @y[5], @y[6], @y[7], @y[8], @y[9]]);
    ...
end;

and it's ok. But if I want to read just one more

var
    x: integer;
    y: array[0..19] of integer;
    s: pchar;
begin
    ...
    sscanf(dataline, "%s %d %d %d %d %d %d %d %d %d %d %d %d",
            [s, @x, @y[0], @y[1], @y[2], @y[3], @y[4],
                    @y[5], @y[6], @y[7], @y[8], @y[9], @y[10]]);
    ...
end;

then I get a runtime error: "The project myproject has thrown an exception of class 'External: SIGSEGV'. at address 82E37E1".

Any ideas of what can go wrong? Thank you very much.

I'm using lazarus 1.2.4 with fpc 2.6.4 in Linux Mint 17.1 32bits.

EDIT: As Abelisto suggested, the issue was about s, I changed it from PChar to String and initialized it with some spaces and everything works fine. The code reads the lines in a TMemo to get the data, then makes a table (in a TListView) adding the values and then the minimum, average and maximum value. Note that 1023 is the maximum value possible.

procedure TfMain.bGetDataClick(Sender: TObject);
const
    dataPoints = 20;
var
    it: TListItem;
    n, i, x, avg, min, max: integer;
    y: array[0 .. dataPoints - 1] of integer;
    dataLine: string;
    s: string = '                ';
begin
    datalist.BeginUpdate;
    datalist.Clear;
    n := -1;
    while n < cSerIn.Lines.Count do
        begin
        Inc(n);
        dataLine := cSerIn.Lines[n];
        sscanf(dataLine, '%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d',
               [@s, @x, @y[0], @y[1], @y[2], @y[3], @y[4],
                        @y[5], @y[6], @y[7], @y[8], @y[9],
                        @y[10], @y[11], @y[12], @y[13], @y[14],
                        @y[15], @y[16], @y[17], @y[18], @y[19]]);

        it := dataList.Items.Add;
        it.Caption := IntToStr(x);
        avg := 0;
        min := 1023;
        max := 0;
        for i := 0 to dataPoints-1 do
            begin
            it.SubItems.Add(IntToStr(y[i]));
            avg += y[i];
            if y[i] < min then min := y[i];
            if y[i] > max then max := y[i];
            end;
        avg := avg div dataPoints;
        it.SubItems.Insert(0, IntToStr(max));
        it.SubItems.Insert(0, IntToStr(avg));
        it.SubItems.Insert(0, IntToStr(min));
        end;
    datalist.EndUpdate;
end;

Also I realized my fpc version is 2.6.4, not 2.6.0. Thanks everyone for the help!

mclopez
  • 151
  • 1
  • 11
  • It is glad to see that you resolve the problem. By the way it is some "hack" in the code where you initializing `s` variable by fixed count of spaces. If you really do not need the first text in the input string, just remove first "text" value from the string you used, like `dataline := Copy(dataline, Pos(' ', dataline) + 1, Length(dataline));` and remove `@s` from `sscanf` – Abelisto Apr 12 '15 at 11:57

1 Answers1

0
program project1;

uses
    sysutils;
const
    CArrCnt = 19;
var
    x: integer;
    y: array[0..CArrCnt] of integer;
    s: string; // changes here
    dataline: string;
    i: Integer;

begin
    dataline := 'aaa 123 0 1 2 3 4 5 6 7 8 9 10 11';
    s := '          '; // changes here
    sscanf(dataline, '%s %d %d %d %d %d %d %d %d %d %d %d %d %d',
        [@s, @x, @y[0], @y[1], @y[2], @y[3], @y[4], @y[5], 
                 @y[6], @y[7], @y[8], @y[9], @y[10], @y[11]]);
    WriteLn(s);
    Writeln(x);
    for i := 0 to CArrCnt do
        WriteLn(y[i]);
    ReadLn;
end.

works fine.

You have to show more of the program code. For example we are not know is memory for s: pchar; was allocated.

BTW: Win7, FPC 3.1.1 32 bit.

Abelisto
  • 14,826
  • 2
  • 33
  • 41
  • No, it does not work fine without some further fine tuning. When I `ideone`-it as `Pascal (fpc)` language snippet, like in https://ideone.com/z9Q8m1 then the result is "_An unhandled exception occurred...: EAccessViolation : Access violation..._" – xmojmr Apr 12 '15 at 03:54
  • @xmojmr Do not use some web s..tuff instead of native desktop app. No one is responsible for the compiler that it uses. – Abelisto Apr 12 '15 at 07:34
  • 1
    @xmojmr I just test this code with FPC 2.6.4 and yes, it throw SIGSEGV. But as I mention above I use FPC 3.1.1 – Abelisto Apr 12 '15 at 07:50
  • I did not find any trace of `sscanf`-related problem in the bug tracker, but may be there was something and it was fixed. Official latest `fpc` release is `2.6.4` so one option might be to fetch latest development `linux` version and try if the error is still reproducible, or download source codes and use debugger to figure out what is wrong. `sscanf` is implemented in http://svn.freepascal.org/svn/fpc/trunk/rtl/objpas/sysutils/sysstr.inc. I'd suspect some `SizeOf(integer) <> SizeOf('%d-variable')` problem or incorrect default `{$PACKRECORDS n}`....? – xmojmr Apr 12 '15 at 08:43
  • @xmojmr This issue may be related to anything. Pointers, strings or something else. In any case it is not the good place to ask about FPC issue. FPC forum is much better in the case if some code works in one ver of the compiler and does not in another. – Abelisto Apr 12 '15 at 08:56
  • @Albeisto so what would be the helpful answer to OP's question "_why sscanf crashes and any ideas to fix it_"? Is it "_dont know, use newer fpc_" or "_dont know, open fpc support ticket_"? In my opinion if the question was asked at Stack Overflow then it should be answered at Stack Overflow or some workaround offered like [Split a string into an array of strings based on a delimiter](http://stackoverflow.com/questions/2625707/split-a-string-into-an-array-of-strings-based-on-a-delimiter) followed by loop with `SysUtils.StrToIntDef`...? – xmojmr Apr 12 '15 at 10:37
  • Keep in mind btw that the code snippet is ambiguous without FPC compiler mode specified. If you run it in some IDE that forces mode delphi or objfpc, sizeof(integer) is 4, while in default (TP,FPC) modes it is 2. – Marco van de Voort Apr 12 '15 at 20:02