Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Komische EAccessViolation (https://www.delphipraxis.net/184314-komische-eaccessviolation.html)

Captnemo 17. Mär 2015 14:20

Komische EAccessViolation
 
Hi,

ich such schon ewig rum, aber ich finde meinen Fehler einfach nicht.
Mittels unten stehender Klasse sammele ich Daten zusammen, die einfach nur in die DB geschrieben werden solle.
Bei der Procedure SaveToDB erhalte eine EAccessViolation. Das ansich ist ja oftmals leicht zu klären. Aber in diesem Fall finde ich einfach nicht, wo es haken soll, weil die Zugriffverletzung, wenn ich das Programm in Einzelschritten durchgehe, genau beim "begin" der Procedure SaveToDB ausgelöst wird.

Der Einfachheithalber habe ich mal die komplette Klasse gepostet.
Tatsächlich ist es aber so, dass ich im Einzelschrittmodus auch noch in die Unit System komme zu einer Funktion (_UStrAddRef) in Assembler, wo dann wirklich der Fehler auftritt. Das jedoch übersteigt meinen Horizont. Ganz unten habe ich das auch noch mal gepostet.

An den Klassen, die ich innerhalb der Procedure nutze kann es meiner Meinung nach nicht liegen, weil a) ich diese auch anderweitig erfolgreich nutze und b) der Fehler ja eigentlich erst an den Stellen auftreten sollte (wenn es denn daran liegt). Aber ich komme ja noch nicht mal über das "begin" hinweg.

Delphi-Quellcode:
              frm_WiegungK.einfahrtswiegung.ausgang:=True;
              WiegungToDB:=TWiegungToDB.Create;
              WiegungToDB.Zeitpunkt:=Now;
              WiegungToDB.BedienerString:=schluesselList[SchlIdx].Code;
              WiegungToDB.Gewicht:=frm_WiegungK.gewicht;
              WiegungToDB.Wiegesatz:='Pförtnerwiegung - Ein: '+
                FormatFloat('#,##0.00 Kg', frm_WiegungK.einfahrtswiegung.eingewicht)+' Aus: '+
                FormatFloat('#,##0.00 Kg', frm_WiegungK.einfahrtswiegung.eingewicht);
              WiegungToDB.SaveToDB(einfahrtswiegung.guid, Waage, LieferantenList, schluesselList);

Delphi-Quellcode:
unit uWiegungToDBK;

interface

uses System.Classes, System.SysUtils, System.DateUtils, Data.DB, SDEngine,
     uLieferantenK, uSchluesselK, uNummernK, uWaagenK;

Type
  TWiegungToDB=class
  private
    FCSh: string;
    FCSl: string;
    FKilo: Integer;
    FZeitpunkt: TDateTime;
    FWiegesatz: string;
    FBedienerString: string;
    FDatum: TDate;
    FCWSString: string;
    FGuid: string;
    FEinfahrtswiegung: string;
    FBediener: Integer;
    FZeit: TTime;
    FCWS: Integer;
    FBrueckennr: Integer;
    FGewicht: Extended;
    procedure SetBediener(const Value: Integer);
    procedure SetBedienerString(const Value: string);
    procedure SetBrueckennr(const Value: Integer);
    procedure SetCSh(const Value: string);
    procedure SetCSl(const Value: string);
    procedure SetCWS(const Value: Integer);
    procedure SetCWSString(const Value: string);
    procedure SetDatum(const Value: TDate);
    procedure SetEinfahrtswiegung(const Value: string);
    procedure SetGewicht(const Value: Extended);
    procedure SetGuid(const Value: string);
    procedure SetKilo(const Value: Integer);
    procedure SetWiegesatz(const Value: string);
    procedure SetZeit(const Value: TTime);
    procedure SetZeitpunkt(const Value: TDateTime);
  public
    procedure SaveToDB(guidEinfahrt: string; waage: TWaage; LieferantenList: TLieferantenList; SchluesselList: TSchluesselList);
  published
    property Guid: string read FGuid write SetGuid;
    property CWSString: string read FCWSString write SetCWSString;
    property CWS: Integer read FCWS write SetCWS;
    property BedienerString: string read FBedienerString write SetBedienerString;
    property Bediener: Integer read FBediener write SetBediener;
    property Zeitpunkt: TDateTime read FZeitpunkt write SetZeitpunkt;
    property Datum: TDate read FDatum write SetDatum;
    property Zeit: TTime read FZeit write SetZeit;
    property Gewicht: Extended read FGewicht write SetGewicht;
    property Kilo: Integer read FKilo write SetKilo;
    property Brueckennr: Integer read FBrueckennr write SetBrueckennr;
    property Wiegesatz: string read FWiegesatz write SetWiegesatz;
    property CSl: string read FCSl write SetCSl;
    property CSh: string read FCSh write SetCSh;
    property Einfahrtswiegung: string read FEinfahrtswiegung write SetEinfahrtswiegung;
  end;

const
  NullGUID='{00000000-0000-0000-0000-000000000000}';

implementation

function Bool2Int(b: Boolean): Integer;
begin
  if b then
    Result:=1 else
    Result:=0;
end;

function Int2Bool(i: Integer): Boolean;
begin
  Result:=i<>0;
end;

{ TWiegungToDB }

procedure TWiegungToDB.SaveToDB(guidEinfahrt: string; waage: TWaage;
  LieferantenList: TLieferantenList; SchluesselList: TSchluesselList);
var
  q: TSDQuery;
  guid: TGUID;
  SchlIdx, LiefIdx, FrakIdx: Integer;
  Nummern: TNummern;
begin                                          //<----------------Hier tritt der Fehler auf.
  //Datensatz in Datenbank schreiben.
  q:=TSDQuery.Create(nil);
  q.DatabaseName:='gmsql3';
  createGuid(guid);
  self.Fguid:=GUIDToString(guid);
  q.SQL.Text:='Insert into wiegungen (guid, waageguid, waage, datum, schluessel, '+
              'lieferant, lieferantname, artikelguid, artikel, gewicht, wiegenr, '+
              'quittungsnr, quittung, datev, wiegesatz, einfahrtswiegung) VALUES '+
              '(:guid, :waageguid, :waage, :datum, :schluessel, :lieferant, '+
              ':lieferantname, :artikelguid, :artikel, :gewicht, :wiegenr, '+
              ':quittungsnr, :quittung, :datev, :wiegesatz, :einfahrtswiegung)';
  q.Params.ParseSQL(q.SQL.Text, True);
  q.Params.ParamValues['guid']:=Self.FGuid;
  q.Params.ParamValues['waageguid']:=waage.Guid;
  q.Params.ParamValues['waage']:=waage.Waage;
  q.Params.ParamByName('datum').DataType:=ftDateTime;
  q.Params.ParamValues['datum']:=Self.FZeitpunkt;
  q.Params.ParamValues['schluessel']:=Self.FBedienerString;
  SchlIdx:=SchluesselList.IndexOfSchluessel(self.FBedienerString);
  if SchlIdx>-1 then
  begin
    LiefIdx:=LieferantenList.IndexOfGuid(SchluesselList[SchlIdx].Lieferantguid);
    if LiefIdx>-1 then
    begin
      q.Params.ParamValues['lieferant']:=LieferantenList[LiefIdx].Lieferantnr;
      q.Params.ParamValues['lieferantname']:=LieferantenList[LiefIdx].Name;
    end else begin
      q.Params.ParamValues['lieferant']:='0';
      q.Params.ParamValues['lieferantname']:=SchluesselList[SchlIdx].Lieferant;
    end;
  end else begin
    q.Params.ParamValues['lieferant']:='0';
    q.Params.ParamValues['lieferantname']:='Unbekannt';
  end;
  FrakIdx:=waage.Fraktionen.IndexOfFraktionnr(self.FCWS);
  if FrakIdx>-1 then
  begin
    q.Params.ParamValues['artikelguid']:=waage.Fraktionen[FrakIdx].Artikelguid;
    q.Params.ParamValues['artikel']:=waage.Fraktionen[FrakIdx].Artikel;
  end else begin
    q.Params.ParamValues['artikelguid']:=NullGUID;
    q.Params.ParamValues['artikel']:='Konnte nicht ermittelt werden';
  end;
  q.Params.ParamValues['gewicht']:=Self.FGewicht;
  Nummern:=TNummern.Create;
  q.Params.ParamValues['wiegenr']:=Nummern.Wiegenr;
  Nummern.Free;
  q.Params.ParamValues['quittungsnr']:=0;
  q.Params.ParamValues['quittung']:=Bool2Int(False);
  q.Params.ParamValues['datev']:=Bool2Int(False);
  q.Params.ParamValues['wiegesatz']:=self.Wiegesatz;
  q.Params.ParamValues['einfahrtswiegung']:=guidEinfahrt;
  q.ExecSQL;
  q.Free;
end;

procedure TWiegungToDB.SetBediener(const Value: Integer);
begin
  FBediener := Value;
end;

procedure TWiegungToDB.SetBedienerString(const Value: string);
begin
  FBedienerString := Value;
end;

procedure TWiegungToDB.SetBrueckennr(const Value: Integer);
begin
  FBrueckennr := Value;
end;

procedure TWiegungToDB.SetCSh(const Value: string);
begin
  FCSh := Value;
end;

procedure TWiegungToDB.SetCSl(const Value: string);
begin
  FCSl := Value;
end;

procedure TWiegungToDB.SetCWS(const Value: Integer);
begin
  FCWS := Value;
end;

procedure TWiegungToDB.SetCWSString(const Value: string);
begin
  FCWSString := Value;
end;

procedure TWiegungToDB.SetDatum(const Value: TDate);
begin
  FDatum := Value;
end;

procedure TWiegungToDB.SetEinfahrtswiegung(const Value: string);
begin
  FEinfahrtswiegung := Value;
end;

procedure TWiegungToDB.SetGewicht(const Value: Extended);
begin
  FGewicht := Value;
end;

procedure TWiegungToDB.SetGuid(const Value: string);
begin
  FGuid := Value;
end;

procedure TWiegungToDB.SetKilo(const Value: Integer);
begin
  FKilo := Value;
end;

procedure TWiegungToDB.SetWiegesatz(const Value: string);
begin
  FWiegesatz := Value;
end;

procedure TWiegungToDB.SetZeit(const Value: TTime);
begin
  FZeit := Value;
end;

procedure TWiegungToDB.SetZeitpunkt(const Value: TDateTime);
begin
  FZeitpunkt := Value;
end;

end.
Delphi-Quellcode:
function _UStrAddRef(Str: Pointer): Pointer;
{$IFDEF PUREPASCAL}
var
  P: PStrRec;
begin
  Result := Str;
  if Str <> nil then
  begin
    P := Pointer(PByte(Str) - SizeOf(StrRec));
    if P.refcnt >= 0 then
      AtomicIncrement(P.refcnt);
  end;
end;
{$ELSE !PUREPASCAL}
{$IFDEF CPUX86}
asm
        { ->   EAX    str    }
        TEST   EAX,EAX
        JE     @@exit
        MOV    EDX,[EAX-skew].StrRec.refCnt     //<-----Und hier habe ich dann wirklich die AV
        INC    EDX
        JLE    @@exit
   LOCK INC    [EAX-skew].StrRec.refCnt
@@exit:
end;
{$ENDIF CPUX86}
{$ENDIF !PUREPASCAL}

baumina 17. Mär 2015 14:31

AW: Komische EAccessViolation
 
Warum gibt's hier eine Angabe der Formularinstanz
Delphi-Quellcode:
frm_WiegungK.einfahrtswiegung.ausgang:=True;
und ein Stück weiter unten nicht?
Delphi-Quellcode:
 WiegungToDB.SaveToDB(einfahrtswiegung.guid

Beim Haltepunkt SaveToDB hast du dort die Inhalte von einfahrtswiegung.guid, Waage, LieferantenList und schluesselList überprüft?

BUG 17. Mär 2015 14:35

AW: Komische EAccessViolation
 
Aus der Hüfte geschossen liegt es an der Referenzzählung von "guidEinfahrt". Wo kommt der Wert denn her?
Übergebe mal testweise einen festen String.

jaenicke 17. Mär 2015 15:06

AW: Komische EAccessViolation
 
Schau einmal, ob im Debugger beim begin vielleicht Self nil ist. ;-)

Captnemo 17. Mär 2015 15:38

AW: Komische EAccessViolation
 
Zitat:

Zitat von baumina (Beitrag 1293775)
Warum gibt's hier eine Angabe der Formularinstanz
Delphi-Quellcode:
frm_WiegungK.einfahrtswiegung.ausgang:=True;
und ein Stück weiter unten nicht?
Delphi-Quellcode:
 WiegungToDB.SaveToDB(einfahrtswiegung.guid

Beim Haltepunkt SaveToDB hast du dort die Inhalte von einfahrtswiegung.guid, Waage, LieferantenList und schluesselList überprüft?

Danke. Das wars. Ich hab das bestimmt an die 100 mal durchgelesen, aber jetzt seh ich das zum ersten mal ;)

Jetzt weiß ich auch, warum das beim "begin" passiert ist.

Vielen Dank.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:57 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz