AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Access Violation durch Length(Array)?

Ein Thema von Jumpy · begonnen am 28. Nov 2012 · letzter Beitrag vom 30. Nov 2012
Antwort Antwort
Seite 1 von 2  1 2   
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.733 Beiträge
 
Delphi 6 Enterprise
 
#1

Access Violation durch Length(Array)?

  Alt 28. Nov 2012, 15:36
Delphi-Version: 5
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:
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
Ohne den try...except Block, also nur mit
Code:
Result:=Length(priv_Calls);
kommt die Fehlermeldung nur einmal, mit dem Block kommt es irgendwie zu einer Endlosschleife und die Fehlermeldung kommt immer wieder.
Miniaturansicht angehängter Grafiken
pic1.jpg  
Ralph
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.537 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Access Violation durch Length(Array)?

  Alt 28. Nov 2012, 15:40
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]
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen

Geändert von DeddyH (28. Nov 2012 um 15:48 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.114 Beiträge
 
Delphi 12 Athens
 
#3

AW: Access Violation durch Length(Array)?

  Alt 28. Nov 2012, 15:50
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 )
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.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (28. Nov 2012 um 15:53 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.537 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Access Violation durch Length(Array)?

  Alt 28. Nov 2012, 15:51
Lesen:
Zitat:
Delphi-Quellcode:
//priv_Calls: TTapiCalls;
//TTapiCalls = Array of TTapiCall;
//TTapiCall ein(e) Objekt/Klasse
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.733 Beiträge
 
Delphi 6 Enterprise
 
#5

AW: Access Violation durch Length(Array)?

  Alt 28. Nov 2012, 16:09
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;
Ralph
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.114 Beiträge
 
Delphi 12 Athens
 
#6

AW: Access Violation durch Length(Array)?

  Alt 28. Nov 2012, 16:30
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;
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (28. Nov 2012 um 16:32 Uhr)
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#7

AW: Access Violation durch Length(Array)?

  Alt 28. Nov 2012, 17:42
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;
Andreas
  Mit Zitat antworten Zitat
Bjoerk

Registriert seit: 28. Feb 2011
Ort: Mannheim
1.384 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: Access Violation durch Length(Array)?

  Alt 28. Nov 2012, 17:50
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;
Wenn ich's noch recht in Erinnerung habe, liefert High für Length = 0 Minus Eins zurück.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.114 Beiträge
 
Delphi 12 Athens
 
#9

AW: Access Violation durch Length(Array)?

  Alt 28. Nov 2012, 18:35
High = Length - 1
da dynamische Arrays immer bei Index 0 beginnen.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.733 Beiträge
 
Delphi 6 Enterprise
 
#10

AW: Access Violation durch Length(Array)?

  Alt 29. Nov 2012, 09:21
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:
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;
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).

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
Ralph

Geändert von Jumpy (29. Nov 2012 um 09:51 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 00:25 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