AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi Access Violation 30 Sek. nach letzter Anweisung?
Thema durchsuchen
Ansicht
Themen-Optionen

Access Violation 30 Sek. nach letzter Anweisung?

Ein Thema von Borschti · begonnen am 17. Jun 2008 · letzter Beitrag vom 19. Jun 2008
Antwort Antwort
Borschti

Registriert seit: 1. Nov 2007
Ort: Marburg Lahn
235 Beiträge
 
Delphi 2007 Professional
 
#1

Access Violation 30 Sek. nach letzter Anweisung?

  Alt 17. Jun 2008, 14:01
Hallo,

Ich habe einen Fehler in einem Programm, und zwar handelt es sich um eine Access Violation, an sich keine große Sache aber der Zeitpunkt an dem der Fehler auftritt schon

Also hier ist der Code den ich zum einlesen einer durch Semikolons getrennten Datei benutze:

Delphi-Quellcode:
procedure THauptfenster.mOpenClick(Sender: TObject);
  Var
    Dateiname : string;
begin


if Datenmodul.OpenDialog.Execute then
    begin
      Dateiname := Datenmodul.OpenDialog.Filename;
      if (Dateiname <> '') then
        begin
          if FileExists(Dateiname) then
            begin
              try
                ImportDatei := TStringlist.Create;
                Datenmodul.Dateilesen(Dateiname, ImportDatei);
                StatusBar.Panels[1].Text := ExtractFilename(Dateiname);
                StatusBar.Panels[1].Text := ' ' + Dateiname + ' ' + IntToStr(ImportDatei.Count) + ' Sätze';
          Z_S_AEN:=0;
          Z_S_NEU:=0;
          application.ProcessMessages;
          screen.Cursor:=crhourglass;
                Datenmodul.Datenaufbereiten(ImportDatei, ';', StatusBar.Panels[1]);
                if StatusBar.Panels[1].enabled = false then
                  StatusBar.Panels[1].enabled:= true;
                StatusBar.Panels[0].Text := '';
          screen.Cursor:=crdefault;
          statusbar.Panels[1].text:= 'neu - geändert (S / R / A / B / P ) '
                + inttostr(Z_S_NEU) + '-' + inttostr(Z_S_AEN) + '/ ';
              except
                showmessage ('Fehler ????');
          end;
            end;
        end;
    end;
end;
Also die Access Violation tritt auf nachdem der letzte Schritt dieser Anweisungsfolge durchgeführt wurde. Aber jetzt kommt der Haken, ersten ca 30-40 Sekunden nachdem
Delphi-Quellcode:
statusbar.Panels[1].text:= 'neu - geändert (S / R / A / B / P ) '
        + inttostr(Z_S_NEU) + '-' + inttostr(Z_S_AEN) + '/ ';
ausgeführt wurde, ich bin wirklich am verzweifeln

Habe mir die Nummern Notiert welche mir ausgegeben wurden als die Fehlermeldung auftrat:

Access Violation at 0x11d6e54e at Adress 0x0337a391 vielleicht kann ja jemand was damit anfangen oder mir erklären was ich damit anfangen könnte

Sorry das der Code so verunstaltet ist, wird automatisch hier eingerückt


Schonmal danke für eure Antworten.

mfg
Alex
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.858 Beiträge
 
Delphi 11 Alexandria
 
#2

Re: Access Violation 30 Sek. nach letzter Anweisung?

  Alt 17. Jun 2008, 14:09
-Du gibst die Stringliste nicht mehr frei
-StatusBar.Panels[1].Text := ExtractFilename(Dateiname); ist so überflüssig, da ja sofort wieder überschreiben wird
-Was macht Datenaufbereiten()?
Markus Kinzler
  Mit Zitat antworten Zitat
Borschti

Registriert seit: 1. Nov 2007
Ort: Marburg Lahn
235 Beiträge
 
Delphi 2007 Professional
 
#3

Re: Access Violation 30 Sek. nach letzter Anweisung?

  Alt 17. Jun 2008, 15:16
Also hab die StringList freigegeben, hat aber nichts genützt.

Datenaufbereiten:

Delphi-Quellcode:
procedure Datenaufbereiten(ParamListe : TStringlist; ParamTrenner : string; ParamPanel : TVisiStatusPanel);
var
  Zaehler : Integer;
  Feldliste : TStringlist;
  Datenliste : TStringlist;
  AktFeld : Integer;
begin
  (* Erzeugung einer Stringlist fuer die Speicherung der Feldangaben *)
  Feldliste := TStringlist.Create;
  (* Erzeugung einer Stringlist fuer die Zwischenspeicherung der Dateninhalte einer Textzeile *)
  Datenliste := TStringlist.Create;

  (* Schliessen der temporaeren Tabelle *)
  DataModule1.TempDaten.Active := false;

  (* Wenn die uebergebene Liste, die alle Textzeilen der Textdatei enthaelt, existiert, dann... *)
  if ParamListe <> nil then
    begin
     (* Wenn die uebergebene Liste auch wirklich Zeilen hat, dann... *)
      if ParamListe.Count > 0 then
        begin
          (* ... wird als erstes die Datenstruktur der temporaeren Tabelle aufgebaut. Dazu *)
          (* werden die Feldbeschreibungen (FieldDefs) zunaechst geloescht.                *)
          DataModule1.TempDaten.FieldDefs.Clear;

          (* Die erste Zeile (ACHTUNG: Indexwert 0) wird in ihre Bestandteile (Feldanga-)  *)
          (* aufgespalten. Der Feldtrenner wird dabei an die Prozedur DatenTrennen durch-  *)
          (* gereicht.                                                                     *)
          DatenTrennen(ParamListe.Strings[0], ParamTrenner, FeldListe);

          (* Der Einfachheit halber, werden in der temporaeren Tabelle nur Felder vom Da-  *)
          (* tentyp String und einer Dimension von 30 Zeichen angelegt. Mittels FOR-       *)
          (* Schleife wird die Feldliste vom ersten bis zum letzten Eintrag abgearbeitet.  *)
          (* Wiederum ist zu beachten, dass der Index mit 0 und nicht mit 1 beginnt.       *)
          for Zaehler := 0 to Feldliste.Count - 1 do
            begin
              (* With-Konstrukt vereinfacht die Angabe von Eigenschaften. *)
              with DataModule1.TempDaten Do
                begin
                  (* Mit der Methode IndexOf wird geprueft, ob in den FieldDefs schon ein  *)
                  (* Feld mit dem aktuellen Feldnamen existiert. Ein Feldname darf nicht   *)
                  (* doppelt vergeben werden. Wenn die Moeglichkeit besteht, dass ein Feld *)
                  (* mehrfach benoetigt wird, muesste in einem Else-Zweig ein Ersatzkon-   *)
                  (* strukt gebildet werden, das evtl. mit einem laufenden Zaehler zur Un- *)
                  (* scheidung der Felder beitraegt. In diesem Beispiel wird darauf jedoch *)
                  (* verzichtet.                                                           *)
                  if FieldDefs.IndexOf(AnsiUpperCase(Feldliste.Strings[Zaehler])) < 0 then
                    FieldDefs.Add(AnsiUpperCase(Feldliste.Strings[Zaehler]), ftString, 30, False);

                end;
            end;

          (* Die Tabelle Land, die fuer die Demonstration eines Lookup-Feldes in der Tabelle *)
          (* TempDaten benoetigt wird, muss vor der eigentlichen Tabelle geoeffnet werden.   *)
          DataModule1.Land.Active := true;

          (* Oeffnen der temporaeren Tabelle namens TempDaten. Ueber einen Editor ist ein    *)
          (* Lookup- und ein CalcField angelegt worden. *)
          DataModule1.TempDaten.Active := true;

          (* Die Datenzeilen aus der uebergebenen Stringlist werden verarbeitet. Da die Da-  *)
          (* ten ab der zweiten Zeile angenommen werden, ist als Startwert fuer die FOR-     *)
          (* Schleife auf 1 zu setzen (entspricht dem 2. Element der Liste!).                *)
          for Zaehler := 1 to ParamListe.Count - 1 do
            begin
              (* Die Prozedur DatenTrennen kann fuer die Datenzeilen auch verwendet werden, weil *)
              (* fuer die Funktionalitaet unerheblich ist, ob es sich um die erste Zeile mit der *)
              (* Feldbeschreibung handelt oder eine der nachfolgenden Datenzeilen. Alle Zeilen   *)
              (* enthalten schliesslich einzelne Elemente, die mit einem Trennzeichen (z.B. Se-  *)
              (* mikolon) voneinander getrennt sind. Uebergeben wird hier jedoch eine zweite     *)
              (* Stringlist, die fuer die Zwischenspeicherung der Daten vorbehalten ist.         *)
              DatenTrennen(ParamListe.Strings[Zaehler], ParamTrenner, Datenliste);

              (* Wenn die Anzahl der Feldbeschreibungen mit der Anzahl der gefundenen Daten-     *)
              (* elemente uebereinstimmt, ist die Wahrscheinlichkeit gross, dass die Struktur in *)
              (* Ordnung ist. Bei einer Abweichung muss sind entweder zu viele oder zu wenige    *)
              (* Informationen in der Datenzeile. Ursache kann eine "missbraeuchliche" Nutzung   *)
              (* des Trennzeichens sein. Das kann vor allem bei einem Komma als Trennzeichen     *)
              (* auftreten sofern bei Gleitkommazahlen auch ein Komma uebergeben wird.           *)
              if Feldliste.Count = Datenliste.Count then
                begin
                  (* Datensatz in der temporaeren Tabelle anfuegen und in den Editiermodus schalten. *)
                  (* Die Append-Methode sorgt fuer beides, so dass die Edit-Methode nicht aufgerufen *)
                  (* wird.                                                                           *)
                  DataModule1.TempDaten.Append;

                  (* Mit einer FOR-Schleife koennen alle Felder durchlaufen werden *)
                  For AktFeld := 0 to Datenliste.Count - 1 do
                    begin
                      with DataModule1.TempDaten Do
                        begin
                          (* Fieldbyname-Methode zum Ansprechen eines Datenfeldes mit dem in der  *)
                          (* Stringlist gespeicherten Feldnamen. Da die Reihenfolge der Feld- und *)
                          (* Datenzeile identisch sein soll, kann die Zuordnung des Inhalts ein-  *)
                          (* fach ueber den Index erfolgen.                                       *)
                          Fieldbyname(Feldliste.Strings[AktFeld]).Asstring := Datenliste.Strings[AktFeld];
                        end;
                    end;
                  (* Nach der Zuweisung aller Daten kann der Datensatz gespeichert werden. Dieses *)
                  (* geschieht mit der Post-Methode der Tabelle.                                  *)
                  DataModule1.TempDaten.Post;
                end;

              (* Pruefung, ob ein Statusbar-Panel uebergeben wurde. Soll der Fortschritt nicht    *)
              (* angezeigt werden, reicht es aus, der Prozedur anstelle des Objekts den Wert NIL  *)
              (* mitzugeben also z.B. Datenaufbereiten(Datenliste; ';', nil).                     *)
              if ParamPanel <> nil then
                begin
                  (* Panel sichtbar machen *)
                  ParamPanel.Enabled := true;
                  (* GaugeAttrs nutzbar, wenn das Panel vom Typ skGauge ist. Die Eigenschaft Po-  *)
                  (* sition gibt den Wert an, den der Fortschrittsbalken erhalten soll. In diesem *)
                  (* Fall wird eine prozentuale Darstellung gewaehlt. Die mathematische Funktion  *)
                  (* DIV wird zur Division genutzt, weil so ein ganzzahliger Wert ermittelt wird, *)
                  (* wie es von der Eigenschaft verlangt wird. Diese Funktion wird gerne gemein-  *)
                  (* sam mit der Funktion MOD gelehrt. Sie fuehrt ebenfalls eine Division durch,  *)
                  (* gibt dann aber den ganzzahligen Rest zurueck.                                *)
                  (* Beispiele:                                                                   *)
                  (*              5 / 2 = 2.5,   5 DIV 2 = 2,  5 MOD 2 = 1                        *)
                  (*             10 / 2 = 5  ,  10 DIV 2 = 5, 10 MOD 2 = 0                        *)
                  ParamPanel.GaugeAttrs.Position := Zaehler * 100 div (ParamListe.Count - 1);

                  (* Mit ProcessMessages wird eine Windows-Message abgesendet, deren Konsequenz   *)
                  (* ein Refresh der Anwendung ist.                                               *)
                  Application.ProcessMessages;
                end;

            end;

          (* Panel unsichtbar machen *)
          if ParamPanel <> nil then
            ParamPanel.Enabled := false;
        end;
    end;

  (* den Speicher der Stringlisten wieder freigeben und die Objekte eliminieren *)
  FreeAndNil(Datenliste);
  FreeAndNil(FeldListe);
end;
dazu noch Datentrennen:

Delphi-Quellcode:
procedure Datentrennen(ParamZeile, ParamTrenner : string; Var ParamListe : TStringlist);
var
  TrennPos : integer;
  StartPos : integer;
  Zaehler : integer;
  MyMsg : string;
begin
    (* Uebergebene TStringlist wird geleert *)
    ParamListe.Clear;

    (* Ausgangswert fuer die Suche des Trennzeichens innerhalb der Zeichenkette. Die Funktion *)
    (* PosEx (Unit StrUtils) unterstuetzt im Gegensatz zur Funktion Pos die Suche einer       *)
    (* Zeichenfolge ab einer definierten Position. Zunaechst soll ab der 1. Stelle gesucht    *)
    (* werden.                                                                                *)
    StartPos := 1;

    (* TrennPos nimmt den Rueckgabewert von PosEx áuf und stellt die Position der gesuchten   *)
    (* Zeichenkette dar.                                                                      *)
    TrennPos := PosEx(ParamTrenner, ParamZeile, StartPos);

    (* Sofern ein Trennzeichen gefunden wurde... *)
    while (TrennPos > 0) do
      begin
        (* ... wird mit der Funktion Copy ab dem Ausgangswert bis zum Trennzeichen eine Zeichen- *)
        (* kette herauskopiert und der Stringlist angefuegt.                                     *)
        Paramliste.Add (COPY(ParamZeile, StartPos, TrennPos - StartPos));

        (* Um zu pruefen, ob ein weiteres Trennzeichen in der Zeichenkette vorkommt, wird der    *)
        (* Ausgangswert erhoeht. Dabei wird zu der Position des zuletzt gefundenen Trennzeichens *)
        (* der Wert 1 addiert.                                                                   *)
        StartPos := TrennPos + 1;
        TrennPos := PosEx(ParamTrenner, ParamZeile, StartPos);
      end;

    (* Zeichenkette fuer die Ausgabe der Stringlist wird mit einem Leerstring initialisiert      *)
    MyMsg := '';

    (* In die Zeichenkette werden alle Elemente der Stringlist eingefuegt. Fuer eine uebersicht- *)
    (* liche Darstellung wird nach jedem Element jeweils ein Zeilenumbruch (englisch Carriage    *)
    (* Return [CR]) angefuegt, der im ASCII-Zeichensatz mit dem Wert 13 definiert ist.           *)
    for Zaehler := 0 to ParamListe.Count -1 do
      begin
        MyMsg := MyMsg + ParamListe.Strings[Zaehler] + #13;
      end;

    (* Ausgabe der Stringlist in einer Messagebox *)
    //showmessage(MyMsg);
end;
Hoffe das hilft dir weiter, ich kann einfach keinen Fehler finden da die Prozeduren auch in anderen Programmen zum Einsatz kommen glaube ich auch nicht das hier der Fehler liegt.

mfg
Alex
  Mit Zitat antworten Zitat
Benutzerbild von RavenIV
RavenIV

Registriert seit: 12. Jan 2005
Ort: Waldshut-Tiengen
2.875 Beiträge
 
Delphi 2007 Enterprise
 
#4

Re: Access Violation 30 Sek. nach letzter Anweisung?

  Alt 17. Jun 2008, 15:19
/offtopic
Du weisst schon, dass man mit // eine ganze Zeile auskommentieren kann?
Man muss dafür nicht das hässliche (* ... *) nehmen.
Klaus E.
Linux - das längste Text-Adventure aller Zeiten...
Wer nie Linux mit dem vi konfiguriert hat, der hat am Leben vorbei geklickt.
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#5

Re: Access Violation 30 Sek. nach letzter Anweisung?

  Alt 17. Jun 2008, 15:26
Der Code geht ja in den Kommentaren unter. Man sollte so wenig wie möglich kommentieren, aber so viel wie nötig.

Und so ein Kommentar:
Delphi-Quellcode:
(* ... wird als erstes die Datenstruktur der temporaeren Tabelle aufgebaut. Dazu *)
          (* werden die Feldbeschreibungen (FieldDefs) zunaechst geloescht.                *)
          DataModule1.TempDaten.FieldDefs.Clear;
ist überflüssig. dass die Feldbschreibunge gelöscht werden, sieht man doch an der Codezeile selber.

Auch der ist überflüssig:
Delphi-Quellcode:
(* Die erste Zeile (ACHTUNG: Indexwert 0) wird in ihre Bestandteile (Feldanga-)  *)
          (* aufgespalten. Der Feldtrenner wird dabei an die Prozedur DatenTrennen durch-  *)
          (* gereicht.                                                                     *)
          DatenTrennen(ParamListe.Strings[0], ParamTrenner, FeldListe);
Das der Index bei null anfängt sollte bekannt sein. Der Rest wird durch die sehr aussagekräftigen Bezeichner selbstkommentierend.

Was ich sagen will, zu viele und zu lange Kommentare stören eher beim Lesen des Codes, als dass sie zu dessen Verständnis beitragen.

Was anderes wäre folgerndes:
DatenTrennen(ParamListe.Strings[1], ParamTrenner, FeldListe); Da wäre ein Kommentar sinnvoll, warum du erst beim zweiten Eintrag anfängst, weil der erste eventuell irgendwelche anderen Daten enthält, die du hier nicht brauchst oder so. Sprich, wenn man etwas ungewöhnliches oder schwer nachzuvollziehendes macht, sind Kommentare angebracht, die hauptsächlich das Warum erklären, das wie sieht man ja am Code.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Borschti

Registriert seit: 1. Nov 2007
Ort: Marburg Lahn
235 Beiträge
 
Delphi 2007 Professional
 
#6

Re: Access Violation 30 Sek. nach letzter Anweisung?

  Alt 17. Jun 2008, 15:34
Ich hab das nicht auskommentiert weil ich das nicht programmiert hab aber kanns gerne rauseditieren wen ihr wollt.

mfg
Alex
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.858 Beiträge
 
Delphi 11 Alexandria
 
#7

Re: Access Violation 30 Sek. nach letzter Anweisung?

  Alt 17. Jun 2008, 15:36
Man könnte auch gleich Stringlisten-Methoden verwenden
Markus Kinzler
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#8

Re: Access Violation 30 Sek. nach letzter Anweisung?

  Alt 17. Jun 2008, 15:37
Das war nur eine allgemeine Anmerkung zu dem Programmierstil. Lass es so.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Borschti

Registriert seit: 1. Nov 2007
Ort: Marburg Lahn
235 Beiträge
 
Delphi 2007 Professional
 
#9

Re: Access Violation 30 Sek. nach letzter Anweisung?

  Alt 19. Jun 2008, 08:53
/kleiner push

Kann mir niemand weiterhelfen?

//Edit: Hat sich erledigt, hing mit dem zu oft gefüllten und erneut geöffnetem Query zusammen.

mfg
Alex
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:38 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