LazarusIDE i Win10 – aplikacja raz na jakiś czas rzuca SIGSEGV przy rozruchu

0

Witam
Używam Lazarusa v1.8.2 z FPC 3.0.4 32bit na Win10 home 64bit.
Przy pisaniu apek mam wyłączoną opcje "Aplikacja graficzna win32" by mieć coś w rodzaju konsoli do wyrzucania wyników poprzez writeln.
Apki to przeważnie jakieś proste interfejsy do baz danych.
Przy uruchomieniu apek (F9) raz jest wszystko OK - apka sie uruchamia - albo nie (jeśli coś pokaszaniłem) - albo wyrzuca błąd :
"Project project1 raised exeption class 'External:SIGSEGV'."
Nawet mimo braku błędów w apce.
Zdarzenie jest nieprzewidywalne i np.: na 4 x F9 bez zmiany kodu 2 razy się normalnie uruchomi a 2 razy się wywali jak zacytowałem wyżej.
Może ktoś coś wie jak z tym sobie poradzić ?

1

Bez kodu trudno wskazać gdzie masz błąd.
SIGSEGV wskazuje na błąd w dostępie do pamięci, czyli np. odwołanie do niezainicjowanego obiektu, wyjście poza rozmiar tablicy ...

0

Bez kodu trudno wskazać gdzie masz błąd.<

Problem w tym iż nie jest tak przy jednej apce tylko przy różnych ale z taką sama konfiguracją

0

Pokaż coś, bo nikt nie będzie zgadywał co masz w kodzie. Podałem dwie najczęstsze przyczyny wyjątku SIGSEGV .

0

Oki :

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, odbcconn, sqldb, pqconnection, DB, FileUtil, Forms,
  Controls, Graphics, Dialogs, StdCtrls, ComCtrls, CheckLst, Grids, DateUtils,
  LConvEncoding, Windows, Types,base64;

type
  pracownik = record
    id:integer;
    name:string;
    lastlog:string;
    hidden:boolean;
  end;

  { TCardRotate }

  TCardRotate = class(TForm)
    Button1: TButton;
    PQDSource: TDataSource;
    PQTrans: TSQLTransaction;
    PQuery: TSQLQuery;
    wskazplikMSA: TButton;
    importMSA: TButton;
    ENDAPP: TButton;
    MSADSource: TDataSource;
    MSAodbc: TODBCConnection;
    PageControl1: TPageControl;
    podajplikbazy: TOpenDialog;
    MSAQuery: TSQLQuery;
    MSATrans: TSQLTransaction;
    PQCon: TPQConnection;
    listaimportu: TStringGrid;
    zakladkaimportu: TTabSheet;
    TabSheet2: TTabSheet;
    procedure Button1Click(Sender: TObject);
    procedure listaimportuClick(Sender: TObject);
    procedure listaimportuDblClick(Sender: TObject);
    procedure wskazplikMSAClick(Sender: TObject);
    procedure importMSAClick(Sender: TObject);
    procedure ENDAPPClick(Sender: TObject);
    procedure FormShow(Sender: TObject);

  private
    { private declarations }
  public
    { public declarations }
    procedure connect;
    procedure ostatniimport;
    procedure wyswietlpracownikow;
    procedure zmienstan(id:integer;stan:boolean);
  end;

var
  CardRotate: TCardRotate;

implementation

{$R *.lfm}

{ TCardRotate }

procedure TCardRotate.FormShow(Sender: TObject);
begin
  writeln('start');
  importMSA.Enabled:=false;
  connect;
  wyswietlpracownikow;
  ostatniimport;

end;

//----------------------------------------------------
procedure TCardRotate.connect;
 var
  plik: TextFile;
  buildPath,oldPath,conffilepatch,daneconf: string;
begin
  conffilepatch:=GetCurrentDir + '\config.txt';
  oldPath := SysUtils.GetEnvironmentVariable('PATH');
  buildPath := oldPath + ';dll\';
  SetEnvironmentVariable('PATH', PChar(buildPath));
  writeln(conffilepatch);
  AssignFile(plik, conffilepatch);
  try
    try
      reset(plik);
      readln(plik, daneconf);
      PQCon.HostName := daneconf;
      readln(plik, daneconf);
      PQCon.UserName := daneconf;
      readln(plik, daneconf);
      PQCon.Password := daneconf;
      readln(plik, daneconf);
      PQCon.DatabaseName := daneconf;
    finally
      PQCon.Connected := True;
      CloseFile(plik);
    end;
  except
     ShowMessage('Problem z połączeniem z bazą lub plikiem konfiguracyjnym. Plik powinien znajdować się tu: '
      + conffilepatch);
    Application.Terminate;
  end;
end;


//----------------------------------------------------
procedure TCardRotate.importMSAClick(Sender: TObject);
var
  zapMSA,zapPQ: string;
  i, ilewiersz: integer;
  pracownicyMSA: array of pracownik;
begin

  MSATrans.Active:=true;
  zapMSA := 'SELECT e.employeeid as id ,(select iif(max(arisetime)<>null,max(arisetime),2) from eventrecord where e.employeeid=employeeid ) as lastlog, e.employeename as name  FROM Employee e order by e.employeeid';
  MSAQuery.SQL.Text := zapMSA;
  MSADSource.DataSet := MSAQuery;
  MSADSource.DataSet.Active := True;
  MSADSource.DataSet.Refresh;
  ilewiersz := MSADSource.DataSet.RecordCount;
  SetLength(pracownicyMSA,ilewiersz+1);
  writeln('dorekordu');
  for i := 0 to ilewiersz  do
    begin
       writeln('rek',i);
         pracownicyMSA[i].name:=CP1250ToUtf8(MSADSource.DataSet.FieldByName('name').Value);
         pracownicyMSA[i].id:=MSADSource.DataSet.FieldByName('id').Value;
         pracownicyMSA[i].lastlog:=FormatDateTime('YYYY-MM-DD',MSADSource.DataSet.FieldByName('lastlog').Value);
         MSADSource.DataSet.Next;
    end;
  MSAQuery.Clear;
  MSAQuery.Close;
  MSADSource.DataSet.Active:=false;
  MSADSource.DataSet.Close;

  for i := 0 to ilewiersz  do
  begin
    zapPQ:='INSERT INTO recorder.user (iduser, iddep, name, hidden, lastlog) VALUES ('+inttostr(pracownicyMSA[i].id)+', '+inttostr(0)+', '''+pracownicyMSA[i].name+''',false,'''+pracownicyMSA[i].lastlog+''') ON CONFLICT (iduser) DO UPDATE SET name = excluded.name, iddep = excluded.iddep, lastlog = excluded.lastlog;';
    PQTrans.Active := False;
    PQuery.sql.Text := zapPQ;
    PQTrans.StartTransaction;
    PQuery.ExecSQL;
    PQTrans.Commit;
    PQuery.Clear;
    PQuery.Close;
  end;
  wyswietlpracownikow;
end;

procedure TCardRotate.ostatniimport;
var
  i,ilewiersz:integer;
  czekstr,zapPQ:string;
begin
    zapPQ:='select count(*) as ilo,max(data) as lastrec from  recorder.record';
    PQuery.sql.Text := zapPQ;
    PQDSource.DataSet := PQuery;
    PQDSource.DataSet.Active := True;
    PQDSource.DataSet.Refresh;
    if (PQDSource.DataSet.FieldByName('ilo').Value>0) then
        begin
        writeln(PQDSource.DataSet.FieldByName('lastrec').Value);
        end;
    PQDSource.DataSet.Active:=false;
    PQDSource.DataSet.Close;
    PQuery.Clear;
    PQuery.Close;
end;


procedure TCardRotate.wyswietlpracownikow;
var
  i,ilewiersz:integer;
  czekstr,zapPQ:string;
begin
    writeln('Z PQ');
    zapPQ:='select * from recorder.user order by name';
    PQuery.sql.Text := zapPQ;
    PQDSource.DataSet := PQuery;
    PQDSource.DataSet.Active := True;
    PQDSource.DataSet.Refresh;
    ilewiersz := PQDSource.DataSet.RecordCount;
    writeln(ilewiersz);
    listaimportu.RowCount:=ilewiersz+1;
    for i := 1 to ilewiersz  do
    begin
      czekstr:='◻';
      if (PQDSource.DataSet.FieldByName('hidden').Value=true) then czekstr:='🗹';
      listaimportu.Cells[0,i]:=czekstr;   //'🗹◻  '
      listaimportu.Cells[1,i]:=PQDSource.DataSet.FieldByName('name').Value;
      listaimportu.Cells[2,i]:=datetostr(PQDSource.DataSet.FieldByName('lastlog').Value);
      listaimportu.Cells[3,i]:=inttostr(PQDSource.DataSet.FieldByName('iduser').Value);
      listaimportu.Cells[4,i]:=booltostr(PQDSource.DataSet.FieldByName('hidden').Value);
      PQDSource.DataSet.Next;
    end;
    PQDSource.DataSet.Active:=false;
    PQDSource.DataSet.Close;
    PQuery.Clear;
    PQuery.Close;
end;

procedure TCardRotate.wskazplikMSAClick(Sender: TObject);
var
    dbconstr:string;
begin
  if podajplikbazy.Execute then
  begin
    dbconstr:='DBQ='+podajplikbazy.FileName;
    MSAodbc.Params.Add(dbconstr);
    MSAodbc.Connected:=true;
   importMSA.Enabled:=true;
  end;
end;

procedure TCardRotate.listaimportuDblClick(Sender: TObject);
var
grid: TStringgrid absolute Sender;
wyb,gridcli: integer;
stan:boolean;
czekstr:string;
begin
  grid := Sender as TStringgrid;
  gridcli := grid.Row;
  writeln(grid.Row,' ',grid.Col);
  wyb:=strtoint(listaimportu.Cells[3,gridcli]);
  stan:=strtobool(listaimportu.Cells[4,gridcli]);
  zmienstan(wyb,stan);
end;


procedure TCardRotate.listaimportuClick(Sender: TObject);
var
grid: TStringgrid absolute Sender;

begin

  grid := Sender as TStringgrid;
  writeln(grid.Row,' ',grid.Col);
end;

procedure TCardRotate.Button1Click(Sender: TObject);
var
  zapMSA,zapPQ: string;
  strtemp:string;
  i, ilewiersz: integer;
  khem,id,cid,oid,dim,tim:string;
begin
  if podajplikbazy.FileName <> '' then
  begin
    MSATrans.Active:=true;
    zapMSA := 'select top 40 EventType,EmployeeID,CtrlID,Ordinal,AriseTime,format(arisetime,''short date'') as sdata,format(arisetime,''long time'') as stime from EventRecord where EventType=1   order by AriseTime';
    MSAQuery.SQL.Text := zapMSA;
    MSADSource.DataSet := MSAQuery;
    MSADSource.DataSet.Active := True;
    MSADSource.DataSet.Refresh;
    ilewiersz := MSADSource.DataSet.RecordCount;

    writeln('dorekordu ', ilewiersz);
    for i := 0 to ilewiersz-1  do
      begin
           id:=inttostr(MSADSource.DataSet.FieldByName('EmployeeID').Value);
           cid:=inttostr(MSADSource.DataSet.FieldByName('CtrlID').Value);
           oid:=inttostr(MSADSource.DataSet.FieldByName('Ordinal').Value);
           tim:=FormatDateTime('hh:nn:ss',MSADSource.DataSet.FieldByName('stime').Value);
           dim:=datetimetostr(MSADSource.DataSet.FieldByName('sdata').Value);
           khem:=inttostr(DateTimeToFileDate (MSADSource.DataSet.FieldByName('AriseTime').Value));

           strtemp:=khem+id+cid+oid;
           writeln('TS: ',khem,' D: ',dim,' T: ',tim,' ID U: ',id,' C ID: ',cid,' Ord: ',oid,' zlep: ',strtemp,' = ',EncodeStringBase64(strtemp));

           MSADSource.DataSet.Next;
      end;
    MSAQuery.Clear;
    MSAQuery.Close;
    MSADSource.DataSet.Active:=false;
    MSADSource.DataSet.Close;
     {
    for i := 0 to ilewiersz  do
    begin
      zapPQ:='INSERT INTO recorder.user (iduser, iddep, name, hidden, lastlog) VALUES ('+inttostr(pracownicyMSA[i].id)+', '+inttostr(0)+', '''+pracownicyMSA[i].name+''',false,'''+pracownicyMSA[i].lastlog+''') ON CONFLICT (iduser) DO UPDATE SET name = excluded.name, iddep = excluded.iddep, lastlog = excluded.lastlog;';
      PQTrans.Active := False;
      PQuery.sql.Text := zapPQ;
      PQTrans.StartTransaction;
      PQuery.ExecSQL;
      PQTrans.Commit;
      PQuery.Clear;
      PQuery.Close;
    end;
    wyswietlpracownikow;
      }

  end
  else showmessage('Nie wskazano pliku bazy do importu !!');

end;



procedure TCardRotate.zmienstan(id:integer;stan:boolean);
var
zapPQ:string;
sortCol:integer;
sortOrder:TSortOrder;
begin
   zapPQ:='UPDATE recorder.user SET hidden='+booltostr(not(stan),true)+' WHERE iduser='+inttostr(id);
     PQTrans.Active := False;
     PQuery.sql.Text := zapPQ;
     PQTrans.StartTransaction;
     PQuery.ExecSQL;
     PQTrans.Commit;
     PQuery.Clear;
     PQuery.Close;
     sortCol:=listaimportu.SortColumn;
     if (sortCol=-1) then sortCol:=1;
     sortOrder:=listaimportu.SortOrder;
     writeln('s: ',sortCol,' t: ',sortOrder);
     wyswietlpracownikow;
     listaimportu.SortColRow(true,sortCol);
     listaimportu.SortOrder:=sortOrder;
end;

function iledniwm(miesiac, rok: integer): integer;
begin
  if ((miesiac = 4) or (miesiac = 6) or (miesiac = 9) or (miesiac = 11)) then
  begin
    iledniwm := 30;
  end
  else if (miesiac = 2) then
  begin
    if (((rok mod 4) = 0) and ((rok mod 100) <> 0)) or ((rok mod 400) = 0) then
    begin
      iledniwm := 29;
    end
    else
    begin
      iledniwm := 28;
    end;
  end
  else
  begin
    iledniwm := 31;
  end;
end;

procedure TCardRotate.ENDAPPClick(Sender: TObject);
begin
  MSAodbc.Connected:=false;
  PQCon.Connected := false;
  Application.Terminate;   // -------------------------------exit
end;

function DecodeStringBase64(const s:string):String;

var instream,outstream : TStringStream;
    decoder : TBase64DecodingStream;
begin
  instream:=TStringStream.Create(s);
  try
    outstream:=TStringStream.Create('');
    try
      decoder:=TBase64DecodingStream.create(instream,bdmmime);
      try
         outstream.copyfrom(decoder,decoder.size);
         outstream.position:=0;
         result:=outstream.readstring(outstream.size);
      finally
        decoder.free;
        end;
    finally
     outstream.free;
     end;
  finally
    instream.free;
    end;
end;

function EncodeStringBase64(const s:string):String;

var outstream : TStringStream;
    encoder : TBase64EncodingStream;
begin
  outstream:=TStringStream.Create('');
  try
    encoder:=TBase64EncodingStream.create(outstream);
    try
      encoder.write(s[1],length(s));
    finally
      encoder.free;
      end;
    outstream.position:=0;
    result:=outstream.readstring(outstream.size);
  finally
    outstream.free;
    end;
end;

end.
0

Szukał bym błędu w dostępie do tablicy pracownicyMSA.
Nie podoba mi się ten fragment kodu, dlaczego rozmiar tablicy jest większy o jeden od liczby wierszy w datasetcie ?

  SetLength(pracownicyMSA,ilewiersz+1);
  writeln('dorekordu');
  for i := 0 to ilewiersz  do
    begin
       writeln('rek',i);
         pracownicyMSA[i].name:=CP1250ToUtf8(MSADSource.DataSet.FieldByName('name').Value);
         pracownicyMSA[i].id:=MSADSource.DataSet.FieldByName('id').Value;
         pracownicyMSA[i].lastlog:=FormatDateTime('YYYY-MM-DD',MSADSource.DataSet.FieldByName('lastlog').Value);
         MSADSource.DataSet.Next;
    end;

EDT1
masz kilka akcji podpięte pod buttony, napisz która z nich generuje wyjątek

EDT2
podobnie jest ze stringgridem listaimportu, którego liczba wierszy też jest większa o jeden od liczby wierszy w datasecie

0
  1. Ponieważ ilość wierszy jest liczone od 0 a SetLength od 1 (zdaje się ) , ale
    2.Tak jak zauważyłeś większość zdarzeń dzieje się po interakcji z użytkownikiem - a wyjątek występuje zanim zobaczę wygenerowane okno apki (widać tylko pustą konsole)
0

Ad. 1
Nie widzisz że liczba iteacji pętli for jest większa o jeden od liczby wierszy w datasecie ?
Zrób tak :

  SetLength(pracownicyMSA,ilewiersz);
  writeln('dorekordu');
  for i := 0 to high(pracownicyMSA)  do
    begin
       writeln('rek',i);
         pracownicyMSA[i].name:=CP1250ToUtf8(MSADSource.DataSet.FieldByName('name').Value);
         pracownicyMSA[i].id:=MSADSource.DataSet.FieldByName('id').Value;
         pracownicyMSA[i].lastlog:=FormatDateTime('YYYY-MM-DD',MSADSource.DataSet.FieldByName('lastlog').Value);
         MSADSource.DataSet.Next;
    end;

Ogólnie to masz bałagan w indeksowaniu zarówno tablic jak i wierszy w StringGridzie, raz wypełniasz od elementu o indeksie zero, innym razem od elementu o indeksie jeden

0

Ad.1. Właściwie efekt jest taki sam - ale jak wspomniałem - ta operacja jest wykonywana po interwencji użytkownika.
Ad.2. to co wyżej - listaimportu ma wiersz z nagłówkami
Ponownie dodam : wyjątek występuje zanim zobaczę wygenerowane okno apki (widać tylko pustą konsole)

Dodatkowo jest taki oto kod na początku

procedure TCardRotate.FormShow(Sender: TObject);
begin
  writeln('start'); 

Ja tego start nie widze

0

więc szukaj błędu w metodzie FormShow

1 użytkowników online, w tym zalogowanych: 0, gości: 1