Search code examples
pascallazarusfreepascalscanf

Why sscanf crashes when adding more variables?


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!


Solution

  • 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.