Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Zugriffsverletzung (https://www.delphipraxis.net/71178-zugriffsverletzung.html)

Koller 10. Jun 2006 10:46


Zugriffsverletzung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

wenn ihr die exe im Anhang startet und dann auf das Symbol für Neue Datei klickt, dann erscheint ein neuer Tab. Nun klickt man auf den letzten Knopf mit dem X und dieser verschwindet. Anschließend klickt man wieder auf den letzen Knopf und es tritt eine Zugriffsverletzung auf. Die Procedure DeleteSubject in der maf.pas wird beim Klicken aufgerufen. Kann jemand den Fehler finden??? :f

Der_Unwissende 10. Jun 2006 10:54

Re: Zugriffsverletzung
 
Zitat:

Zitat von Koller
Kann jemand den Fehler finden??? :f

Klar, aber wie wär's denn wenn du dieser jmd. bist?

Wenn eine Zugriffsverletzung auftritt, nachdem etwas verschwindet, ist es nicht weiter schwer einen möglichen Fehler zu finden. Mit hoher Wahrscheinlichkeit findet wohl ein Zugriff auf ein gelöschtes Objekt statt. Also musst du nur dafür sorgen, dass du nicht auf etwas freigebenes zugreifst. Hab jetzt nicht in deinen Code geschaut, aber prüfen ob eine Variable noch zugewiesen ist macht man mit assigned(Variable) und beim Freigeben kannst du mit FreeAndNil(Variable) sicherstellen, dass der gespeicherte Zeiger nach dem Freigeben der Nullpointer ist.

Gruß Der Unwissende

Koller 10. Jun 2006 11:14

Re: Zugriffsverletzung
 
Ich habe mal den Debugger benutzt. Mit F7 gehe ich Zeile für Zeile durch. Der Debugger springt in die markierte Zeile und danach wird der Fehler ausgelöst.

Delphi-Quellcode:
procedure TMarkFile.DeleteSubject(Sender : TObject);
var row,i,i2:integer;
begin
  row:=(Sender as TButton).Tag;
  if row=High(FEingabeArray) then
  begin
    for i2 := 1 to 5 do
    begin
      FreeAndNil(FEingabeArray[row].array_edit[i2]);
    end;
    FreeAndNil(FEingabeArray[row].button_loeschen);
    FreeAndNil(FEingabeArray[row].Combobox_fach);
  end else
  begin
    for i := row to High(FEingabeArray)-1 do
    begin
      for i2 := 1 to 5 do
      begin
        FEingabeArray[i].array_edit[i2].text:=FEingabeArray[i+1].array_edit[i2].Text;
      end;
      FEingabeArray[i].button_loeschen.Tag:=FEingabeArray[i+1].button_loeschen.Tag;
      FEingabeArray[i].Combobox_fach.Text:=FEingabeArray[i+1].Combobox_fach.Text;
    end;
      FreeAndNil(FEingabeArray[High(FEingabeArray)].button_loeschen);
      FreeAndNil(FEingabeArray[High(FEingabeArray)].Combobox_fach);
      for i2 := 1 to 5 do
      begin
        FreeAndNil(FEingabeArray[High(FEingabeArray)].array_edit[i2]);
      end;
  end;
  SetLength(FEingabeArray,Length(FEingabeArray)-1);
  UpdateSubjects;
end;//hier nach end; wird der Fehler ausgelöst. Danach kommt nichts mehr.

xaromz 10. Jun 2006 11:23

Re: Zugriffsverletzung
 
Hallo,

kann es sein, dass Du den button löschst, der gerade gedrückt wurde? In diesem Fall passiert nämlich Folgendes:
- Button.DoClick wird ausgelöst
- Eigenes Ereignis OnClick wird ausgeführt
- Button wird zerstört
- Rücksprung zu Button.DoClick, aber Button ist nicht mehr vorhanden -> AV

Gruß
xaromz

Koller 10. Jun 2006 11:36

Re: Zugriffsverletzung
 
Ja so wird es sein :autsch: Und was kann man dagegen tun?

xaromz 10. Jun 2006 12:55

Re: Zugriffsverletzung
 
Hallo,
Zitat:

Zitat von Koller
Ja so wird es sein :autsch: Und was kann man dagegen tun?

Du kannst Dir eine eigene Message bauen und diese mit PostMessage an Dein TForm schicken.
Da PostMessage die Message in die Warteschlage steckt, kommt diese nach dem Buttonclick an. In der Behandlungsroutine kannst Du dann den Button zerstören.

Hier hab' ich sowas mal beschrieben.

Gruß
xaromz

Koller 10. Jun 2006 15:35

Re: Zugriffsverletzung
 
Hab ich gemacht, aber der Button verschwindet nicht :roll:

Koller 10. Jun 2006 15:40

Re: Zugriffsverletzung
 
Delphi-Quellcode:
procedure TMarkFile.LoeschMich(var Msg: TMessage);
begin
  TObject(Msg.WParam).Free; // WParam nach TObject casten und freigeben
  showmessage('blubb');
end;
Das wird gar nicht aufgerufen.

SirThornberry 10. Jun 2006 15:56

Re: Zugriffsverletzung
 
dann sendest du wohl die message nicht

Koller 11. Jun 2006 20:14

Re: Zugriffsverletzung
 
Ich hab das nicht abgespeichert, darum kann ich den modifizierten Source nicht mehr herzeigen. Meine Bitte: Kann das mal bitte jemand anpassen? :oops:

Koller 12. Jun 2006 11:13

Re: Zugriffsverletzung
 
Das komische ist ja, dass die alte Version funktioniert:
Delphi-Quellcode:
procedure TForm1.DeleteSubject(Sender : TObject);
var row,i,i2:integer;
begin
  row:=(Sender as TButton).Tag;
  if row=High(EditsArray) then
  begin
    for i2 := 1 to 6 do
    begin
      EditsArray[row][i2].Free;
    end;
    BtnLoeschenArray[row].Free;
  end else
  begin
    for i := row to High(EditsArray)-1 do
    begin
      for i2 := 1 to 6 do
      begin
        EditsArray[i][i2].text:=EditsArray[i+1][i2].text;
      end;
      BtnLoeschenArray[i].Tag:=BtnLoeschenArray[i+1].Tag;
    end;
      for i2 := 1 to 6 do
      begin
        EditsArray[High(EditsArray)][i2].Free;
      end;
      BtnLoeschenArray[High(EditsArray)].Free;
  end;
  SetLength(EditsArray,Length(EditsArray)-1);
  SetLength(BtnLoeschenArray,Length(BtnLoeschenArray)-1);
  UpdateSubjects;
end;
Und die neue:
Delphi-Quellcode:
 
procedure TMarkFile.DeleteSubject(Sender : TObject);
var row,i,i2:integer;
begin
  row:=(Sender as TButton).Tag;
  if row=High(FEingabeArray) then
  begin
    for i2 := 1 to 5 do
    begin
      FreeAndNil(FEingabeArray[row].array_edit[i2]);
    end;
    FreeAndNil(FEingabeArray[row].button_loeschen);
    FreeAndNil(FEingabeArray[row].Combobox_fach);
  end else
  begin
    for i := row to High(FEingabeArray)-1 do
    begin
      for i2 := 1 to 5 do
      begin
        FEingabeArray[i].array_edit[i2].text:=FEingabeArray[i+1].array_edit[i2].Text;
      end;
      FEingabeArray[i].button_loeschen.Tag:=FEingabeArray[i+1].button_loeschen.Tag;
      FEingabeArray[i].Combobox_fach.Text:=FEingabeArray[i+1].Combobox_fach.Text;
    end;
      FreeAndNil(FEingabeArray[High(FEingabeArray)].Combobox_fach);
      FreeAndNil(FEingabeArray[High(FEingabeArray)].button_loeschen);
      for i2 := 1 to 5 do
      begin
        FreeAndNil(FEingabeArray[High(FEingabeArray)].array_edit[i2]);
      end;
  end;
  SetLength(FEingabeArray,Length(FEingabeArray)-1);
  UpdateSubjects;
end;
funktioniert nicht, obwohl ich vom Prinzip her nichts geändert habe. Ich habe nur die verschiedenen Komponenten in ein array of record gepackt.

marabu 13. Jun 2006 11:55

Re: Zugriffsverletzung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Koller,

ich habe mir dein Projekt herunter geladen und den Code angepasst, damit das Löschen funktioniert. Ich finde du solltest bestimmte Teilaspekte deines Projektes zuerst isoliert ausprobieren und testen. Dein Code zeigt deutlich, dass du auf dem besten Weg bist die Übersicht zu verlieren. Wenn du schon soetwas wie ein Multi-Document-Interface realisieren möchtest, dann musst du auch dafür sorgen dass es in deiner Form1 eine Eigenschaft ActiveFile gibt, über die man die richtige Komponente TMarkFile selektieren kann.

Viel Spaß noch mit deinem Projekt.

marabu

Koller 13. Jun 2006 16:34

Re: Zugriffsverletzung
 
Erst mal vielen Dank!
Hast du nur diese Prozedur geändert?
Delphi-Quellcode:
procedure TMarkFile.DeleteSubject(rowIndex: Integer);
var
  iRow, iEdit: Integer;
begin
  for iRow := rowIndex to Pred(High(FEingabeArray)) do
  begin
    for iEdit := 1 to 5 do
      FEingabeArray[iRow].array_edit[iEdit].text := FEingabeArray[Succ(iRow)].array_edit[iEdit].Text;
    FEingabeArray[iRow].button_loeschen.Tag := FEingabeArray[Succ(iRow)].button_loeschen.Tag;
    FEingabeArray[iRow].Combobox_fach.Text := FEingabeArray[Succ(iRow)].Combobox_fach.Text;
  end;

  with FEingabeArray[High(FEingabeArray)] do
  begin
    for iEdit := 1 to 5 do
      array_edit[iEdit].Free;
    Combobox_fach.Free;
    button_loeschen.Free;
  end;
  SetLength(FEingabeArray, High(FEingabeArray));
  UpdateSubjects;
end;
Zitat:

Zitat von marabu
dann musst du auch dafür sorgen dass es in deiner Form1 eine Eigenschaft ActiveFile gibt, über die man die richtige Komponente TMarkFile selektieren kann.

Ich kann doch mit über Form1.Pagecontrol1.ActivePageIndex-1 den Index des richtigen Objekts herausbekommen?!?! :roll:

marabu 13. Jun 2006 17:31

Re: Zugriffsverletzung
 
Es sind schon noch ein paar Änderungen mehr. Besorge dir WinMerge (2.5MB) und du wirst sie sehen. Relevant für dein Löschproblem ist eigentlich nur die Entkopplung des OnClick event handlers vom eigentlichen Löschvorgang (DeleteSubject). Alle anderen Änderungen habe ich auf halbem Weg wieder rückgängig genmacht, damit du dein Programm noch erkennst.

Zitat:

Zitat von Koller
Ich kann doch über Form1 .Pagecontrol1 .ActivePageIndex-1 den Index des richtigen Objekts herausbekommen?!

Warum willst du jedesmal nach dem richtigen Objekt suchen, wenn du mit einer leicht zu pflegenden Eigenschaft einen direkten Zeiger darauf bereit halten kannst?

Freundliche Grüße

marabu

Koller 13. Jun 2006 17:43

Re: Zugriffsverletzung
 
Zitat:

Zitat von marabu
Warum willst du jedesmal nach dem richtigen Objekt suchen, wenn du mit einer leicht zu pflegenden Eigenschaft einen direkten Zeiger darauf bereit halten kannst?

An eine Property für Klasse TForm1 dachte ich auch schon. Wie würde so etwas mit einem Zeiger aussehen?

marabu 13. Jun 2006 18:03

Re: Zugriffsverletzung
 
Eine property hast du schnell deklariert:

Delphi-Quellcode:
type
  TForm1 = class(TForm)
  private
    ActiveFileIndex: Integer;
    function GetActiveFile: TMarkFile;
  public
    property ActiveFile: TMarkFile read GetActiveFile;
  end;

function TForm1.GetActiveFile: TMarkFile;
begin
  Result := Files[ActiveFileIndex];
end;
Das Feld ActiveFileIndex musst du ständig in Übereinstimmung mit den Aktionen des Benutzers aktualisieren. Zuvor solltest du dir ein paar Gedanken zur Benutzerschnittstelle und zu deiner Programmstruktur machen. Ich vermisse ein Konzept. So läufst du Gefahr eine Menge überflüssigen Code zu schreiben, der später mühevoll raus operiert werden muss.

marabu

Koller 13. Jun 2006 18:16

Re: Zugriffsverletzung
 
Zitat:

Zitat von marabu
Eine property hast du schnell deklariert:

Delphi-Quellcode:
type
  TForm1 = class(TForm)
  private
    ActiveFileIndex: Integer;
    function GetActiveFile: TMarkFile;
  public
    property ActiveFile: TMarkFile read GetActiveFile;
  end;

function TForm1.GetActiveFile: TMarkFile;
begin
  Result := Files[ActiveFileIndex];
end;

Genauso wollte ich das auch machen :cheers: Aber wegen dem Zeiger war ich irritert.
Zitat:

Zitat von marabu
Das Feld ActiveFileIndex musst du ständig in Übereinstimmung mit den Aktionen des Benutzers aktualisieren. Zuvor solltest du dir ein paar Gedanken zur Benutzerschnittstelle und zu deiner Programmstruktur machen. Ich vermisse ein Konzept. So läufst du Gefahr eine Menge überflüssigen Code zu schreiben, der später mühevoll raus operiert werden muss.

Ich war bisher immer der Meinung, da wäre ein (bisschen) Konzept drin :duck:
Kannst du mir nen Ansatz geben, weil ich von alleine weiterkommen möchte

marabu 13. Jun 2006 18:59

Re: Zugriffsverletzung
 
Als erstes rate ich dir auf verschachtelte PageControls zu verzichten. Auf der zweiten Ebene deines Programms ist das auch garnicht hilfreich. Durch deinen Button "Daten auswerten" ist ein Sekundärfenster die bessere Lösung. Nimm die Seite Datenauswertung ganz weg und mache die Seite Dateneingabe direkt zu einer Seite der ersten Ebene.

Auf der ersten Ebene hast du einen Reiter "HomePage". Wenn alle folgenden Seiten gleichartig sind, dann solltest du auf eine andersartige erste Seite unbedingt verzichten.

Die von dir dann überarbeitete Komponente TMarkFile sollte dann nicht der Verwalter des zugehörigen TabSheets sein, sondern das TabSheet sollte über seine Tag property auf das zugehörige TMarkFile verweisen.

Vielleicht ist es dir nicht bekannt, aber ScreenEx birgt in diesen Zeiten die Gefahr einer Abmahnung. Informiere dich mal.

marabu

Koller 13. Jun 2006 19:09

Re: Zugriffsverletzung
 
Zitat:

Zitat von marabu
Als erstes rate ich dir auf verschachtelte PageControls zu verzichten. Auf der zweiten Ebene deines Programms ist das auch garnicht hilfreich. Durch deinen Button "Daten auswerten" ist ein Sekundärfenster die bessere Lösung. Nimm die Seite Datenauswertung ganz weg und mache die Seite Dateneingabe direkt zu einer Seite der ersten Ebene.

Auf der ersten Ebene hast du einen Reiter "HomePage". Wenn alle folgenden Seiten gleichartig sind, dann solltest du auf eine andersartige erste Seite unbedingt verzichten.

Die von dir dann überarbeitete Komponente TMarkFile sollte dann nicht der Verwalter des zugehörigen TabSheets sein, sondern das TabSheet sollte über seine Tag property auf das zugehörige TMarkFile verweisen.

Dankeschön! Ich versuche es umzusetzen :wink: :thumb:
Zitat:

Zitat von marabu
Vielleicht ist es dir nicht bekannt, aber ScreenEx birgt in diesen Zeiten die Gefahr einer Abmahnung. Informiere dich mal.

Wie kommst du darauf? Deswegen? (Biotec-Filter usw.) --> http://www.google.de/search?hl=de&q=...le-Suche&meta= oder ist das so ne Verarsche wie 'Kennt ihr Mike Rosoft?'

Koller 15. Jun 2006 15:46

Re: Zugriffsverletzung
 
*push*

marabu 15. Jun 2006 15:53

Re: Zugriffsverletzung
 
Entschuldige, aber welche Antwort erwartest du von mir? Ich bin kein Jurist.

Freundliche Grüße vom marabu

Koller 15. Jun 2006 15:56

Re: Zugriffsverletzung
 
Zitat:

Zitat von marabu
Entschuldige, aber welche Antwort erwartest du von mir? Ich bin kein Jurist.

Ist ja ok ;) Ich möchte nur wissen, wie du zu dieser Aussage kommst:
Zitat:

Vielleicht ist es dir nicht bekannt, aber ScreenEx birgt in diesen Zeiten die Gefahr einer Abmahnung. Informiere dich mal.

marabu 15. Jun 2006 16:24

Re: Zugriffsverletzung
 
Verstehe. Das war nur ein gut gemeinter Hinweis von mir - mehr nicht. S... ist ein Produkt und andernorts eine Firma. Ich würde mir einen unverfänglicheren Namen suchen.

Freundliche Grüße

marabu

mkinzler 15. Jun 2006 17:15

Re: Zugriffsverletzung
 
Zitat:

Ich würde mir einen unverfänglicheren Namen suchen.
Schließlich gibt es da einen rechtsanwalt G. und andere, die hier Geld riechen könnten.

Koller 15. Jun 2006 19:02

Re: Zugriffsverletzung
 
Zitat:

Zitat von mkinzler
Zitat:

Ich würde mir einen unverfänglicheren Namen suchen.
Schließlich gibt es da einen rechtsanwalt G. und andere, die hier Geld riechen könnten.

Ich glaube, es ist am besten, man schreibt "© 2006 [Vor- und Nachname]" - dann kann einem nichts passieren :mrgreen:


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:20 Uhr.

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