Access Violation bei Prozeduraufruf aus dynamischem Array

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Chefkoch
Beiträge: 12
Registriert: Do 2. Sep 2010, 15:48

Access Violation bei Prozeduraufruf aus dynamischem Array

Beitrag von Chefkoch »

Guten Abend!
Folgendes Problem:
Bei meienm derzeitigen Projekt übergebe ich dem Konstrukter einer Klasse ein dynamisches Array von Prozedurenadressen. Zweck dessen ist es später auf auftreffende Fehler zu reagieren und die demensprechende Prozedur aufzurufen. Mein Code dazu sieht wie folt aus:

Code: Alles auswählen

type 
  TErrorProc = procedure (aID: Integer; aData: Array of Byte) of object;
  TMyClass = class
  public
    ErrorProcs: Array of TErrorProc;
    constructor Create(ErProcs: Array of TErrorProc);
  end;
 
constructor Create(ErProcs: Array of TErrorProc);
var
  i: Integer;
begin
  SetLength(ErrorProcs, Length(ErProcs));
  for i := 0 to High(ErProcs) do begin
    ErrorProcs[i] := ErProcs[i];
  end;
end;
 
ErrorProcs[ID](ID, Data); //Bei solchen Aufrufen krieg ich eine Acces Violation und das Programm stürzt ab
.......

Also ich kann mir das nicht erklären... wär super nett wenn jemand den Fehler findet ; )
LG Chefkoch

Keifor
Beiträge: 31
Registriert: Sa 28. Aug 2010, 15:15
OS, Lazarus, FPC: pc-linux-gnu - Funtoo stable, L trunk, FPC trunk
CPU-Target: i686/x86_64

Re: Access Violation bei Prozeduraufruf aus dynamischem Array

Beitrag von Keifor »

Der Code hat genügend Fehlerpotential (wenn man nur die paar Zeilen sieht ;) ),
  1. Klassiker: Open Array vs. Dynamisches Array.

    Code: Alles auswählen

    Create(ErProcs: Array of TErrorProc); // open array
    aber

    Code: Alles auswählen

    type
      TErrorProcField = Array of TErrorProc;
    Create(ErProcs: TErrorProcField); // dynamisches array

    Analog mit dem array of Byte im Methodenzeiger. Das kracht öfter mal. Daher hab ich mir z.B. auch angewöhnt immer einen eigenen Typ für Dynamische Felder zu Deklarieren.
  2. Klassiker: Prüfe ob das Übergebene Feld Korrekt ist, Initialisiert etc...
  3. Klassiker: Prüfe ob die ID korrekt ist
  4. Prüfe ob da auch wirklich Methoden zugewiesen werden.. wenn ich mich recht erinnere ist es auch möglich Funktionen zuzuweisen (oder zu casten), auch wenn der Aufruf dann Müll ist
  5. Prüfe ob die Objekte überhaupt noch leben... leider ist die Dokumentation an der Stelle etwas lax und so ein Methodenzeiger ist mehr oder minder Implementierungs-abhängig. Soweit ich weiß besteht ein Methodenzeiger aus (zeiger auf) Instanz + (zeiger auf) Methode.. (oder evt. VMT index), dementsprechend kann es zu allerlei Fehler kommen wenn da was nicht stimmt.

Ich tippe mal auf 1. wenn wirklich ein Dynamisches Feld übergeben wird.
Ansonsten ist das beste ist die offensichtlichen Sachen zu prüfen und sonst mit nem Debugger ran zu gehen.

Chefkoch
Beiträge: 12
Registriert: Do 2. Sep 2010, 15:48

Re: Access Violation bei Prozeduraufruf aus dynamischem Array

Beitrag von Chefkoch »

So..
Bin zwar noch am Testen aber dein "klassicher Fehler Nummer 1" scheint wohl zuzutreffen ; )
Morgen Abend denke ich weiß ich genaueres.

mtbf40
Beiträge: 72
Registriert: Do 3. Nov 2011, 16:39

Re: Access Violation bei Prozeduraufruf aus dynamischem Arra

Beitrag von mtbf40 »

Hallo,

ich sitze jetzt schon Stunden an folgenden Problem:
ich erstelle ein dynamisches Array von einem Record. Danach will ich diese Array an eine Prozedur übergeben - was aber nicht funktioniert...

... wo liegt jetzt das Problem???

Code: Alles auswählen

 
program maint_cli;
 
{$mode objfpc}{$H+}
 
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, SysUtils, Windows, CustApp, RegExpr
  { you can add units after this };
 
type
  spflotR = record
     tester : string;
     dns_nn : string;
     ip_nn  : string;
     dns_cc : string;
     ip_cc  : string;
  end;
    { maint_app }
 
  maint_app = class(TCustomApplication)
  protected
    procedure DoRun; override;
  public
    constructor Create(TheOwner: TComponent); override;
    destructor Destroy; override;
    procedure WriteHelp; virtual;
    procedure Logic; virtual;
    procedure CC; virtual;
  end;
 
{ maint_app }
 
procedure maint_app.DoRun;
var
  ErrorMsg, par: String;
  dnsL, sl : TStringList;
  i,ii : Integer;
  dnsA : Array of spflotR;
begin
  // quick check parameters
  if ParamCount = 0 then begin
    WriteHelp;
    Terminate;
    Exit;
  end;
  ErrorMsg:=CheckOptions('h t: typ: fqNF: destD:','help');
  if ErrorMsg<>'' then begin
    ShowException(Exception.Create(ErrorMsg));
    Terminate;
    Exit;
  end;
 
  // parse parameters
  if HasOption('h','help') then begin
    WriteHelp;
    Terminate;
    Exit;
  end;
 
  // fill Array of Record
  dnsL := TStringList.Create;
  sl := TStringList.Create;
 
  dnsL.LoadFromFile('dnsLST1.txt');
  SetLength(dnsA,dnsL.Count-1);
  for i:=1 to dnsL.Count-1 do
  begin
    SplitRegExpr('\t+?',dnsL[i],sl);
    ii := i-1;
    dnsA[ii].tester:=sl[0];
    WriteLn(dnsA[ii].tester);
    dnsA[ii].dns_nn:=sl[1];
    dnsA[ii].ip_nn:=sl[2];
    dnsA[ii].dns_cc:=sl[3];
    dnsA[ii].ip_cc:=sl[4];
    WriteLn(dnsA[ii].ip_cc);
  end;
 
  dnsL.Free;
  sl.Free;
 
  // parse Typ
  par := GetOptionValue('t');
  writeln('Arr_Länge = ' + intToStr(High(dnsA)));
  case LowerCase(par) of
       'logic' : Logic();  <-------- hier soll das Array übergeben werden -> Logic(dnsA)
       'cc'    : CC();
  end;
 
  // stop program loop
  Terminate;
end;
 
constructor maint_app.Create(TheOwner: TComponent);
begin
  inherited Create(TheOwner);
  StopOnException:=True;
end;
 
destructor maint_app.Destroy;
begin
  inherited Destroy;
end;
 
procedure maint_app.WriteHelp;
begin
  { add your help code here }
  writeln();
  writeln('Usage: ',ExeName,' Options [-h|--help -t|typ [Logic|CC|both] -fqNF FullQualifidNameFile -destD destination Directory]');
  writeln();
  writeln(#9,'h|help - show this output');
  writeln(#9,'t|typ  - which Partition will use');
  writeln(#9,'fqNF   - Name of the File that should copy - fqn with path');
  writeln(#9,'dest   - Destination Path');
  writeln();
end;
 
procedure maint_app.Logic(var Arg : ???);
begin
     writeln('bin in Proc logic');
//     for i:=0 do dns_Arr.
end;
 
procedure maint_app.CC;
begin
     writeln('bin in Proc CC');
end;
 
var
  Application: maint_app;
begin
  Application:=maint_app.Create(nil);
  Application.Title:='Maint Suite';
  Application.Run;
  Application.Free;
end.               
 

Bauer321
Beiträge: 465
Registriert: Sa 21. Aug 2010, 21:30
OS, Lazarus, FPC: Windows 7 Ultimate (L 1.2.2 FPC 2.6.4 32-bit)
CPU-Target: 64-Bit
Wohnort: nahe Bremen
Kontaktdaten:

Re: Access Violation bei Prozeduraufruf aus dynamischem Arra

Beitrag von Bauer321 »

Code: Alles auswählen

Type
  spflotR_array = Array of spflotR;
 
dann unten
var
  dnsA: spflotR_array; //oder wie bisher, da dürfte sich nicht viel tun, bin mir aber nicht ganz sicher
 
und dann
 
procedure maint_app.Logic(var Arg :  spflotR_array);
www.mcpatcher.net | www.hoeper.me

Antworten