Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi invalid poiter und access violation (https://www.delphipraxis.net/141604-invalid-poiter-und-access-violation.html)

tkone 12. Okt 2009 15:03


invalid poiter und access violation
 
hi hab ne fehlermeldung beim laden einer datei.
also was macht mein programm:
ich weis dem programm eine datei zu und diese soll in die einzelbestandteile aufgeteilt werden.
Die datei hat einen header und einen rumpf.
der header wird in zwie abschnitte aufgeteilt, wobei ein kleiner teil dazwischen herausgelassen wird(siehe labl weiter_st).
bis dahin funktionierts auch.
nun soll mir das delphi programm den rumpf des programmes byteweise in ein 2D array speichern.
und genau hier bringt mir das programm den fehler "Access violation".
beim beenden des programmes kommt dann die meldung "invalid pointer".

ich glaub ich bin schon betriebsblind, da ich den fehler absolut nicht finde :(


Delphi-Quellcode:
procedure TForm1.Button3Click(Sender: TObject);   //JC5 laden
Label weiter_st, fertig_st;
var
  f: File of Byte;
  F_size, M_size, akt_pos: Integer;
  headerL, header_pos: Integer;
  plat_byte, schuss_byte, plat, schuss: Integer;
  wert: byte;

begin
lokal_max:=0;
edit1.Text:=inttostr(lokal_max);
edit2.Enabled:=true;

openDialog1.Execute;
AFilename:=OpenDialog1.Filename;
Assignfile(f,AFilename);
Reset(f);
F_size:=Filesize(f);
headerL:=134+length(extractfilename(AFilename));
plat_Byte:=801; //x größe des Musers für den array

// Mustergrössen bestimmmen
M_size:=F_size-headerL;
schuss_Byte:=(M_Size)/(plat_Byte);
schuss:= schuss_byte;
schuss_max:= schuss_byte;

// Dynamische Arrays dimensionieren
SetLength(Header_P1, 15);
SetLength(Header_P2, 134-15-1);  //-1, da 1Byte vor Filename noch veränderlich
SetLength(Muster, plat_Byte, schuss_Byte);

Label6.Caption:='max.'+inttostr(schuss_max);
label7.Visible:=true;
label8.Visible:=false;

akt_pos:=0;
plat:=1;
header_pos:=0;

while not eof(f) Do
Begin
  read(f,wert);
  inc(akt_pos);
  // Zwecks Header Informationen
  if akt_pos<headerL+1 Then goto weiter_st;

  Muster[plat,schuss-1]:=wert;
  inc(plat);
  If plat=plat_byte then
    begin
    plat:=0;
    dec(schuss);
    end;

  If schuss=0 Then goto fertig_st;

  weiter_st:
  Begin
    If akt_pos<16 then
      header_P1[akt_pos-1]:=wert;
    If akt_pos>16+(headerL-134) then
      begin
        header_P2[header_pos]:=wert;
        inc(header_pos);
      end;

  End;

End;
fertig_st:
closefile(f);

button2.Visible:=false;
button1.visible:=true;
edit2.Text:='';

end;

tkone 12. Okt 2009 15:31

Re: invalid poiter und access violation
 
ok ich habs durch den debugger und jede menge einzelschritte doch hinbekommen ;)

das programm startet nachdem es den ersten wert des rumpfes verarbeitet hat tatsächlich wieder den programmteil ab label weiter_st.
klar, liegt ja auch in der reihe ^^
habe jetzt ein weiteres label an den anfang gesetzt und mit dem goto befehl gleich hinter die abbruchbedingung schuss=0 gesetzt ;)

Tyrael Y. 12. Okt 2009 15:38

Re: invalid poiter und access violation
 
Label? Goto?

Es ist das Jahr 2009, man glaubt es kaum, aber es gibt Klassen und Prozeduren, in die man das Ganze packen kann. Es soll natürlich immer Leute geben, die gerne eine "Welt"-Prozedur schreiben, in der alles passiert.

Delphi-Quellcode:
procedure ErschaffeWelt(Zeit := 7Tage);
Ich würde dir vorschlagen, daß du deine Prodezdur mal auseinandernimmst udn daraus viele einzelne Prozeduren machst. Du wirst dann erkennen, daß du keine Labels, Goto mehr brauchst und dein Code so simpel aussieht, daß sogar jemand der seit einer Woche programiert erkennen kann, was passieren soll.

Ist ehrlich ein gutgemeinter Rat.

Chris.R 12. Okt 2009 15:42

Re: invalid poiter und access violation
 
Hallo,

die Benutzung von label und goto ist eher unschön, besser wäre es so in der Art:

Delphi-Quellcode:
while not eof(f) Do
Begin
 
  //if akt_pos<headerL+1 Then goto weiter_st;
  if akt_pos >= headerL + 1 then
  begin
    ...

    //If schuss=0 Then goto fertig_st;
    if schluss = 0 then Break;
  end;

  weiter_st:
  Begin
   

  End;

End;
fertig_st:
Ciao Chris

tkone 12. Okt 2009 15:51

Re: invalid poiter und access violation
 
danke

p80286 12. Okt 2009 16:13

Re: invalid poiter und access violation
 
Hallo tkone,

Dein Sourcecode sieht irgendwie nach einer Basic-Übersetzung aus?

Wo ist denn die Definition von "MUSTER" ? Wenn das ein dynamisches array ist und die entsprechende Längenzuweisung fehlt, dann kommen solche Fehler zustande, wie Du sie beschreibst.

zu den gotos schweigt des Dichters Höflichkeit.

Gruß
K-H

tkone 12. Okt 2009 16:39

Re: invalid poiter und access violation
 
Zitat:

Zitat von p80286
Dein Sourcecode sieht irgendwie nach einer Basic-Übersetzung aus?
zu den gotos schweigt des Dichters Höflichkeit.

Ja so in der Art. Das eigentliche Programm ist von 2000 bis 2005 von 2 ehem. Mitarbeitern geschrieben und ständig modifiziert bzw. erweitert wurden.
Das ganze Projekt ist 106MB groß und verwurstet so gut wie alle Delphistrukturen ^^
Meine Aufgabe besteht darin mich in dieses Programm einzuarbeiten und für eine neue Anwendung zu erweitern bzw. umzuarbeiten.
Aufgrund der Größe und Komplexität habe ich die alten Programmstrukturen tw. übernommen.
Daher auch die Verwendungen von zb. label und goto.

Zitat:

Zitat von p80286
Wo ist denn die Definition von "MUSTER" ? Wenn das ein dynamisches array ist und die entsprechende Längenzuweisung fehlt, dann kommen solche Fehler zustande, wie Du sie beschreibst.

Also Muster ist vom Typ MusterT. Den hab ich als Typ Array of Array of Byte erstellt.
Da Muster in mehreren Programmstrulturen verwendet wird ist es global deklariert.
Lediglich die Größe von Muster wird hier gesetzt.
Der eigentliche Fehler lag an einem Array in Kombination mit den Labels.
Der Array Header_P2 wird beschrieben, wenn die aktuelle Position in der Datei > 16+HeaderL-134.
Hatte aber vergessen dass dieser Array nur beschrieben werden soll, bis headerL erreicht ist, denn dann beginnt ja mein Muster.
Delphi hat also weiterhin versucht Header_P2 zu beschreiben, wobei der Arrayberreich zu Ende war.

p80286 12. Okt 2009 16:55

Re: invalid poiter und access violation
 
Mein ehrlich gemeintes Beileid!

Auch wenn es schrecklich klingt, schreib es soweit es geht neu! Du könntest Dir ekelhafte Seiteneffekte einhandeln.

Gruß
K-H

tkone 14. Okt 2009 07:42

Re: invalid poiter und access violation
 
also mein programm funktioniert wie es soll. es lädt die daten ein, teil sie richtig, dannach kann ich einzelne daten verändern und dann die daten in einer neuen datei speichern.

lediglich zwei kleine unschöne effekte tretten auf, wenn die ersten daten im array MUSTER bearbeitet wurden.

1.) nachdem die erste datei geladen und bearbeitet wurde, erhalte ich einen EAccessViolation error, wenn ich in irgendeiner weise das dyn. array MUSTER bearbeiten möchte(SetLength, Finalize, :=nil, ...). besonders SetLength ist aber notwendig, wenn ich eine weitere datei bearbeiten möchte ohne das programm vorher zu beenden.

2.) beim beenden des programms erhalte ich einen Runtime error 216

p80286 14. Okt 2009 15:16

Re: invalid poiter und access violation
 
Hallo tkone,

so ganz fehlerfrei scheint das aber nicht zu sein:

Zitat:

Zitat von tkone
...
1.) nachdem die erste datei geladen und bearbeitet wurde, erhalte ich einen EAccessViolation error, wenn ich in irgendeiner weise das dyn. array MUSTER bearbeiten möchte(SetLength, Finalize, :=nil, ...). besonders SetLength ist aber notwendig, wenn ich eine weitere datei bearbeiten möchte ohne das programm vorher zu beenden.

2.) beim beenden des programms erhalte ich einen Runtime error 216

in beiden Fällen handelt es sich um den Griff in die "Speicher-Schüssel". Wahrscheinlich beförderst Du irgendwo MUSTER in den Orkus (setlength 0 ?) und greifst dann nocheinmal darauf zu.

Hast Du schon den Debugger bemüht?

Gruß
K-H

tkone 15. Okt 2009 07:47

Re: invalid poiter und access violation
 
so hab ich mir das auch gedacht, kann aber keinen fehler finden.

also am besten mal ein bsp.:

alle meine muster haben die breite 801 und unterscheiden sich in der höhe.

scenario 1:
ich lade ein muster ein, dass 801x600 groß ist. lade ich nun sofort ein muster dass eine andere höhe hat, funktioniert alles einwandfrei.
der array wird auf die entsprechende größe verändert und mit den neuen werten gefüllt.

scenario 2:
ich lade ein muster von 801x600 ein. dannach führe ich eine bearbeitung aus. diese bearbeitung betrifft lediglich die 1., 3. und 4. spalte des Arrays. nach der bearbeitung tretten die beiden fehlermeldungen auf, selbst wenn die bearbeitung nix am array verändert, also alle checkboxen not enabled sind.

ich setz mal die bearbeitungroutine hier rein, vielleicht fällt euch was auf.
den debugger hab ich auch schon schritt für schritt bemüht. in scenario 2 ist der array sollange 801x600(mit richtigen bytewerten gefüllt) bis der setlength befehl die größe auf das neue muster verändern möchte. sobald der befehl auf muster zugreift tritt die EAccessViolation auf.
danach hat der array dann die größe des neuen musters und auch deren richtige werte.

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);   //Bereiche einfügen
var
  i: integer;
  AuswahlSG: Byte;
  SD, KS, DZ_B1, DZ_B2: Byte;
  Byte1, Byte3, Byte4: Byte;

begin
Byte1:=0;
Byte3:=0;
Byte4:=0;

case combobox1.ItemIndex of
0: AuswahlSG:=1;
1: AuswahlSG:=2;
2: AuswahlSG:=4;
3: AuswahlSG:=8;
4: AuswahlSG:=16;
5: AuswahlSG:=32;
6: AuswahlSG:=64;
7: AuswahlSG:=128;
end;

SD:=combobox2.ItemIndex;
KS:=8*combobox3.ItemIndex;

case combobox4.ItemIndex of
0..3: DZ_B1:=64*combobox4.ItemIndex;
4..7: DZ_B1:=64*(combobox4.itemindex-4);
end;

case combobox4.ItemIndex of
0..3: DZ_B2:=0;
4..7: DZ_B2:=1;
end;

If strtoint(edit2.text)>schuss_max then
  begin
  showmessage('zu hoher Wert');
  exit;
  end
else
  If strtoint(edit2.text)=schuss_max then
    button2.Visible:=true;

If Checkbox1.checked then
  Byte1:=AuswahlSG;

If Checkbox2.Checked then
  Byte3:=Byte3+SD;

If Checkbox3.Checked then
  Byte3:=Byte3+KS;

If Checkbox4.Checked then
  begin
    Byte3:=Byte3+DZ_B1;
    Byte4:=DZ_B2;
  End;

for i:=lokal_max to strtoint(edit2.Text) do
  begin
    if Checkbox1.Checked then Muster[0,i]:=Byte1;
    Muster[2,i]:=Byte3;
    Muster[3,i]:=Byte4;
  end;

lokal_max:=strtoint(edit2.Text);
edit1.text:=inttostr(lokal_max);

if lokal_max>=schuss_max then
begin
  edit2.Enabled:=false;
  Button1.Visible:=false;
end;
end;

p80286 15. Okt 2009 14:48

Re: invalid poiter und access violation
 
hallo tkone,

zunächst, in der Routine ist mir nichts aufgefallen, was "böse" wäre. aber schau Dir das alles noch einmal genau an:
Delphi-Quellcode:
lokal_max:=strtoint(edit2.Text);
edit1.text:=inttostr(lokal_max);
Da empfehle ich:
Delphi-Quellcode:
lokal_max:=strtoint(edit2.Text);
edit1.Text:=edit2.Text;
....
oder so
...
edit1.Text:=edit2.Text;
lokal_max:=strtoint(edit2.Text);
if lokal_max>=schuss_max then
begin .........
dann spart man sich ein paar prozessorhundertstel.

Was ist mit dem Debugger?
Hast Du dir einmal im Verlauf der Verarbeitung MUSTER (sollte ein Pointer sein) und die Inhalte/Adressen von MUSTER angeschaut?
Schau mal ob sich length(MUSTER) verändert ("Funktionsaufrufe" gestatten nicht vergessen!)

Da Du den Code geerbt hast kann ich verstehen, daß er noch so aussieht. Aber wenn Du jetzt nach Fehlern suchst, und die gibt es ja , renovier ihn - etwas leserlicher und aussagekräftige Variablennamen - das zahlt sich auf jeden Fall aus.

Was mir noch aufgefallen ist:
Delphi-Quellcode:
// Mustergrössen bestimmmen
M_size:=F_size-headerL;
schuss_Byte:=(M_Size)/(plat_Byte); //<<<<<< Fehler!!!!
schuss:= schuss_byte;
schuss_max:= schuss_byte;
Das Ergebnis von M_Size/Plat_Byte ist KEIN Integer!
(schuss_Byte:=M_Size div plat_Byte; ist besser)
Da sollte der Compiler aber sehr meckern! hast du vielleicht alle Prüfungen abgeschaltet die es gibt?

Gruß
K-H

tkone 15. Okt 2009 15:11

Re: invalid poiter und access violation
 
Zitat:

Zitat von p80286
Was ist mit dem Debugger?
Hast Du dir einmal im Verlauf der Verarbeitung MUSTER (sollte ein Pointer sein) und die Inhalte/Adressen von MUSTER angeschaut?
Schau mal ob sich length(MUSTER) verändert ("Funktionsaufrufe" gestatten nicht vergessen!)

Das Ergebnis von M_Size/Plat_Byte ist KEIN Integer!
(schuss_Byte:=M_Size div plat_Byte; ist besser)
Da sollte der Compiler aber sehr meckern! hast du vielleicht alle Prüfungen abgeschaltet die es gibt?

^^ nee, da kommen keine warnungen(hab auch nix abgestellt), da das ergebis immer eine ganzzahl ausspukt.
die relationen von M_Size, Plat_byte und schuss_byte gehen immer auf.

zum debugger:
MUSTER wird geladen, und gefüllt. (setlength und anschließend über eine schleife mit read(f) aus der geladenen datei die werte ausgelesen)
MUSTER wird von mir bearbeitet (s.o.)
MUSTER wird in neuer Datei gespeichert.
neue datei wird geladen.
1 Zeile vor dem neuen setlength von MUSTER ist MUSTER noch identisch mit dem bearbeiteten inhalt und der größe der vorherigen datei.
beim aufruf von setlength mit den neuen abmaßen kommt der EAccessViolation.
danach ist MUSTER mit den neuen Abmaßen(alter inhalt) und wird mit den akuellen werten überschrieben.

habs bereits probiert MUSTER im letzten schritt zu leeren (zb. setlength 0 oder :=nil) funktioniert zwar, aber die fehlermeldung kommt trotzdem beim aufruf des befehls zum leeren.


EDIT:
hab die ersten 4 Spalten von MUSTER auf ein hilfsarray gespeichert(mglw. darf man MUSTER nicht verändern)
dieses hilfsarray wird nun bearbeitet und beim speichern zuerst die spalten 1-4 des hilfsarrays und erst danach die urinfos aus MUSTER ab der spalte 5 geschrieben.
scheint daran gelegen zu haben, denn ich konnte bisher die fehlermeldungen nicht reproduzieren.

p80286 15. Okt 2009 17:02

Re: invalid poiter und access violation
 
hallo tkone,

schön wenn's klappt aber glücklich bin ich damit nicht, da der eigentliche Fehler wohl nur umgangen, aber nicht behoben wird.

zum Teilen:

Delphi-Quellcode:
var
  wert1 : integer;
  wert2 : integer;
  wert3 : integer;
begin
  wert1:=4;
  wert2:=2;
  wert3:=wert1/wert2; ///// [Fehler] Unit1.pas(34): Inkompatible Typen: 'Integer' und 'Extended'
end;
auch wenn nur ganzzalige Ergebnisse kommen sollten, der Compiler mag das nicht. wenn er das nicht anmeckert, stimmt da etwas ganz und gar nicht.

Gruß
K-H

tkone 16. Okt 2009 07:05

Re: invalid poiter und access violation
 
ha ich hab das mit dem dividieren auch anders ^^
KA warum das noch so ober drin steht im quelltext.
hatte den befehl ROUND(wert1 / wert2) drin


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:19 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-2025 by Thomas Breitkreuz