![]() |
Delphi-Version: 5
Access Violation durch Length(Array)?
Liste der Anhänge anzeigen (Anzahl: 1)
Bei obiger Funktion kommt es immer mal wieder zu einer Fehlermeldung (siehe Bild). Habs auch schon mit High(priv_Calls)+1 versucht. Ich vermute immer dann, wenn priv_Calls keine Elemente (mehr) hat, aber kann das sein? Warum liefert Length nicht einfach 0 und gut ist?
Delphi-Quellcode:
Ohne den try...except Block, also nur mit
function TTapiLine.CallCount: integer;
begin Result:=0; try Result:=Length(priv_Calls); except on e:Exception do showmessage(e.message); end; end; //priv_Calls: TTapiCalls; //TTapiCalls = Array of TTapiCall; //TTapiCall ein(e) Objekt/Klasse
Code:
kommt die Fehlermeldung nur einmal, mit dem Block kommt es irgendwie zu einer Endlosschleife und die Fehlermeldung kommt immer wieder.
Result:=Length(priv_Calls);
|
AW: Access Violation durch Length(Array)?
Wie ist es mit
Delphi-Quellcode:
:?:
function TTapiLine.CallCount: integer;
begin if Assigned(priv_Calls) then Result:=Length(priv_Calls) else Result:=0; end; Möglicherweise ist das Array ja bereits aufgeräumt worden, das kann man ja mit SetLength oder mit Setzen auf nil bewerkstelligen. [edit] Obwohl: auch da müsste doch Length eigentlich 0 sein, wenn ich mich nicht irre. [/edit] |
AW: Access Violation durch Length(Array)?
Assigned hilft eigentlich nichts, denn genau das Selbe macht Length intern auch. (is praktisch nur doppeltgemoppelt)
[edit] Jupp, "leer" = nil. Was ist priv_Calls? (übersehn :oops:) Und was machst du damit? (wie wird es z.B. befüllt) Nja, wenn ich raten müßte (anhand der wenigen vorhandenen Informationen), dann würde ich erstmal an einen Buffer-Overrun denken, mit dem du dir dein Array zerschossen hast. :glaskugel: |
AW: Access Violation durch Length(Array)?
Lesen:
Zitat:
|
AW: Access Violation durch Length(Array)?
Hier mal wie das Array befüllt und geleert wird. Mag sein, dass die Remove-Methode noch etwas umständlich ist, die hab ich noch nicht überarbeitet, vllt. wird da auch das Array zerschossen?
Delphi-Quellcode:
procedure TTapiLine.AddCall(Call: TTapiCall);
begin SetLength(priv_Calls,High(priv_Calls)+2); priv_Calls[High(priv_Calls)]:=Call; end; procedure TTapiLine.AddCall(CallHandle: Cardinal); var Call:TTapiCall; begin Call:=TTapiCall.Create(CallHandle); if Call.Initialized then AddCall(Call) else Call.Free; end; procedure TTapiLine.RemoveCall(CallHandle: Cardinal); var i,j:integer; begin if CallCount=0 then exit; i:=low(priv_calls); while (priv_calls[i].Handle<>CallHandle) and (i<high(priv_calls)) do inc(i); if priv_calls[i].Handle=CallHandle then begin for j:=i to high(priv_Calls)-1 do priv_Calls[j]:=priv_Calls[j+1]; Setlength(priv_Calls, High(priv_Calls)); end; end; |
AW: Access Violation durch Length(Array)?
Direkt einen Fehler seh ich in deinen Funktionen eigentlich nicht.
Deine Schleife ist soweit sicher, aber im Notfalls darfst du gerne die Bereichsprüfung in den Projektoptionen aktivieren, welche dann die indize der Array-Zugriffe prüft, ob da nichts außerhalb des Speicherbereichs liegt. (hätte ja sein können, daß du stattdessen einfach alles zusammen per Move verschiebst und nicht jeden Eintrag einzeln) Das was dein Array zerschießt kann aber auch eine komplett andere Codezeile sein ... fremden Speicher darf man auch kaputtmachen und nicht nud den Eigenen. Es kann natürlich auch sein, daß die TTapiLine-Instanz weg ist oder daß dur irgendwo nicht threadsave auf diese Funktionen zugreifst.
Delphi-Quellcode:
procedure TTapiLine.AddCall(Call: TTapiCall);
begin //Call schon im Array drin ist, dann hat dein Remove problemchen, weil es ja nur nach einem Eintrag sucht und nicht nach mehreren SetLength(priv_Calls, Length(priv_Calls)+1); // mit Length ist's hier "verständlicher", was gemacht wird priv_Calls[High(priv_Calls)]:=Call; end; procedure TTapiLine.AddCall(CallHandle: Cardinal); var Call:TTapiCall; begin // nur wenn Initialized keine Exceptions erzeugen kann, dann wird .Free sicher aufgerufen (Fehler im AddCall einfach mal ausgeschlossen) Call:=TTapiCall.Create(CallHandle); if Call.Initialized then AddCall(Call) else Call.Free; end; procedure TTapiLine.RemoveCall(CallHandle: Cardinal); var i,j:integer; begin // durch die umgedrehte und leicht veränderte While-Prüfung, konnte das erste IF entfallen und das Zweite vereinfacht werden, // da im While nur vorhandene und davon alle Einträge geprüft werden i := Low(priv_calls); while (i < Length(priv_calls)) and (priv_calls[i].Handle <> CallHandle) do // oder (i <= High(priv_calls)) inc(i); if i < Length(priv_calls) then begin for j := i+1 to High(priv_Calls) do priv_Calls[j-1] := priv_Calls[j]; // sprechender Code ... -1 = 1 vorkopieren (OK, das alte +1 = von dahinter herholen geht notfalls och) Setlength(priv_Calls, Length(priv_Calls)-1); // wie oben end; end; |
AW: Access Violation durch Length(Array)?
Höchstwahrscheinlich operierst du auf einem Nil-Objekt rum.
Das Problem ist nicht, dass priv_Calls = Nil sein könnte sondern dass self = Nil ist.
Delphi-Quellcode:
function TTapiLine.CallCount: integer;
begin // diese Sicherheitsabfrage schlägt Alarm bevor Schlimmeres passiert // Assertions müssen in den Projektoptionen natürlich zugelassen sein Assert(Assigned(self)); Result:=0; try Result:=Length(priv_Calls); except on e:Exception do showmessage(e.message); end; end; |
AW: Access Violation durch Length(Array)?
Zitat:
|
AW: Access Violation durch Length(Array)?
High = Length - 1
da dynamische Arrays immer bei Index 0 beginnen. |
AW: Access Violation durch Length(Array)?
Edit: Fehler gefunden. Diesen Post gerne überspringen und unten weiterlesen!
Hallo und guten Morgen und danke für die Hilfe gestern. Eine Nacht drüber geschlafen brachte immer noch keine Lösung. Hab's so geändert, das bei AddCall nun eine globale Zählervariable hochgezählt wird, bei removeCall wird diese wieder runtergesetzt und die Funktion CallCount liest diese nun nur noch aus:
Delphi-Quellcode:
Trotzdem kommt noch der Fehler. Zudem kommt der dann nochmal bei dem showmessage (womit ich sehen wollte, welche Line den Fehler verursacht, was aber nicht klappt). Dies legt den Verdacht nahe, das shmia vllt. die richtige Idee hatte, aber das Assert macht nichts? In den Debug-Optionen ist es aktiviert (überlauf usw. sind deaktiviert).
function TTapiLine.CallCount: integer;
begin { Result:=0; try Result:=Length(priv_Calls); except end;} Assert(Assigned(self)); try Result:=priv_CallCount; except on e:exception do begin showmessage(IntToStr(priv_LineNumber)); end; end; end; Zum Fehler nochmal: Er tritt scheinbar immer nur 1 mal auf 2-5 Sekunden nach Programmstart, danach (hab's mal 30 min laufen lassen) nicht mehr. Vllt. ist da wirklich am Anfang irgendeine "Geisterleitung" die mir hier in den Kram spukt. Das ganze Programm wird durch Tapi-Aufrufe einer Callback-Funktion gesteuert. Mag sein, dass diese schon zu früh mal feuert, wenn noch nicht alle Leitungen stehen oder so. Muss ich mal weiter experimentieren. Andere Ideen aber weiterhin willkommen :-D |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:03 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