Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzung??? (https://www.delphipraxis.net/125399-bitte-code-pruefen-bekomme-immer-eine-zugriffsverletzung.html)

SimStar001 5. Dez 2008 11:07


Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzung???
 
Hallo liebe Delphi Gemeinde,


Und zwar Prüfe ich über einen Timer (Interval 500ms), wer gerade im Teamspeak auf einem Channel auf dem Man connected ist spricht!

Soweit so gut, es klappt auch, nur nach ca. 15 - 20 Minuten wird immer eine Exception ausgelöst. und zwar eine Zugriffsverletzung in meiner Programm.exe

Könntet Ihr euch den Code bitte mal ansehen, vielleicht endeckt ihr ja einen Fehler, oder den Grund für dieses Verhalten

Hier der Code:

Delphi-Quellcode:
function GetTSSpeaker : pchar;
Function DisplayResult( Res: Integer ) : Boolean;
Var
  ErrorMessage: array[0..1023] of Char;
begin
  if res=0 then
  begin
    //Writeln('OK');
    Result := True;
    exit;
  end
  else
  begin
    tsrGetLastError(@ErrorMessage, SizeOf(ErrorMessage));
    Result := False;
  end;
end;

function DoGetPlayers : boolean;
var
  PlayersInfo : Array[0..1023] of TtsrPlayerInfo;
  Records : Integer;
  I: integer;
begin
  result := true;
  Records := 1024;
  try
    if not DisplayResult(tsrGetPlayers(@playersInfo, @records) ) then ;


  if Records > 0 then
  setlength(Player,records);
  if records > 0 then
    begin
    for I :=0 to Records-1 do
      begin
      PLayer[i].id := PlayersInfo[i].PlayerID;
      Player[i].Name := PlayersInfo[i].NickName;
      end;
    result := true;
    end;
  except
    On E:Exception Do
        begin
        hLog.AddException(E);
        exit;
        end;
  end;
end;

function DoGetSpeakers : pchar;
var
  IDs : Array[0..1023] of Integer;
  Records : Integer;
  I: integer;
  PlayersInfo : Array[0..1023] of TtsrPlayerInfo;
  ID : integer;
begin
  result := '';
  Records := 1024;
  try
 if not DisplayResult(tsrGetSpeakers(@playersInfo, @records) ) then exit;
  if Records > 0 then ;
  for I :=0 to Records-1 do
    ID := PlayersInfo[i].PlayerID ;

  for i:= 0 to high(Player) do
    if Player[i].id = Id then
      result := pchar(player[i].Name);
  except
    On E:Exception Do
        hLog.AddException(E);
        end;
end;

begin
  result := '';
  if DOGetPlayers then
    try
    result := DogetSpeakers;
      except
        On E:Exception Do
        hLog.AddException(E,'Function GetTSSpeaker', []);
        end;
end;

Hier der TimerCode

Delphi-Quellcode:
procedure TForm1.Timer3Timer(Sender: TObject);
var TSSpeaker : string;
    i : integer;
begin
  TSSpeaker := GetTSSpeaker;
end;

Delphi-Quellcode:
type Player_ = record
      ID : integer;
      Name : string;
      end;


var Player : array of player_;

Ich danke schonmal für eure Hilfe

Tyrael Y. 5. Dez 2008 11:14

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Wo und wie ist Player deklariert?

SimStar001 5. Dez 2008 11:17

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Sorry, das Hatte ich vergessen

Player ist Global deklariert:

Delphi-Quellcode:

type Player_ = record
      ID : integer;
      Name : string;
      end;


var Player : array of player_;

Tyrael Y. 5. Dez 2008 12:47

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Du Logst doch schon die Ausnahme selbst.
Wie wäre es, wenn du auch loggst in welcher Funktion?

Delphi-Quellcode:
   ...
  except
    On E:Exception Do
    begin
        hLog.AddException('DerMethodenName', E);
    end;
  end;

mashutu 5. Dez 2008 12:51

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
tsrGetSpeakers(@playersInfo, @records)
???

nahpets 5. Dez 2008 13:02

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Hallo,

in der Fehlermeldung bekommst Du doch bestimmt auch die Fehleradresse!

Also Debugger marsch:

Breakpoint auf die erste Programmzeile in der Programm.dpr setzen, Programm starten, hält am Breakpoint an, Menü Suchen, Laufzeitfehler suchen, Adresse aus der Fehlermeldung eingeben und suchen lassen.

Jetzt solltest Du (mit recht großer Wahrscheinlichkeit) an der Stelle im Quelltext landen, an der der Fehler zu suchen ist.

Machmal und zeig' uns dann in Deinem Quelltext die entsprechende Stelle, vielleicht ist's dann ein bisserl weniger :glaskugel:

SimStar001 5. Dez 2008 13:21

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
OK werd ich mal machen, kann nur eine weile dauern bis der fehler auftritt! ich meld mich wieder mit mehr details

SirThornberry 5. Dez 2008 13:25

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Wie lautet denn nun die genaue Fehlermeldung inklusive der Adressen welche in der Fehlermeldung enthalten sind?

DeddyH 5. Dez 2008 13:26

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Öhm, Jens:
Zitat:

Zitat von nahpets
in der Fehlermeldung bekommst Du doch bestimmt auch die Fehleradresse!

Also Debugger marsch:

Also abwarten ;)

shmia 5. Dez 2008 13:36

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Dein Code hat eine schlechte Qualität.
Hier ein Beispiel für eine Funktion, die gleich mehrere Fehler/Mängel hat:
Delphi-Quellcode:
function DoGetSpeakers : pchar; // warum Pchar ? string ist viel sicherer
var
  IDs : Array[0..1023] of Integer;
  Records : Integer;
  I: integer;
  PlayersInfo : Array[0..1023] of TtsrPlayerInfo; // Unschön und gefährlich: grosse Arrays auf dem Stack (Stacküberlauf droht)
  ID : integer;
begin
  result := '';
  Records := 1024; // unschön, hier wäre Length(PlayersInfo) angebracht
  try
  if not DisplayResult(tsrGetSpeakers(@playersInfo, @records) )
    then exit;
  if Records > 0 then ; // diese Zeile tut nichts. Warum steht sie dann da ?

  for I :=0 to Records-1 do
    ID := PlayersInfo[i].PlayerID ; // Unsinn: ID wird zugewiesen - es wird aber damit nicht gearbeitet

  for i:= 0 to high(Player) do       // wenn i > Records-1, dann wird auf uninitialisierten Daten gearbeitet !!! ein ganz böses Foul
    if Player[i].id = Id then
      result := pchar(player[i].Name); // Schleife läuft weiter, obwohl der Player mit der Id gefunden wurde
                                       // fehlt da nicht ein Break ?
  except
    On E:Exception Do
        hLog.AddException(E);
        end; // Einrückung passt nicht
end;

SimStar001 5. Dez 2008 14:49

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Danke fürs durchschauen des Codes.

Also zur Erklärung, der Code wurde so von Teamspeak Programmierern übernommen, der ja frei zugänglich ist, und nur wenig verändert:

Dies ist laut TeamSpeak Beispiel korrekt (sollte es denke ich mal, hab TS ja nicht programmiert):

Delphi-Quellcode:
PlayersInfo : Array[0..1023] of TtsrPlayerInfo;

Records := 1024;

for i:= 0 to high(Player) do // Record wurde ja auf 1024 begrenzt, bzw werden wohl nicht mehr als 1024 player online sein oder dürfen laut TS?

if Player[i].id = Id then
      result := pchar(player[i].Name);
//Die Schleife läuft weiter weil ja mehrere Sprechen können, und ich mich der sich auch af dem channel befindet nicht angezeigt haben möchte, sprich ich und noch jemand sprechen gleichzeitig, dann brauche ich nur seine ID und nicht meine
Was den rest betrifft, habe ich den code auch wenn er scheinbar nichts macht stehengelassen!



PS: Programm wird gerade getestet!

shmia 5. Dez 2008 15:12

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Delphi-Quellcode:
for i:= 0 to high(Player) do // Record wurde ja auf 1024 begrenzt, bzw werden wohl nicht mehr als 1024 player online sein oder dürfen laut TS?
der Aufruf von tsrGetSpeakers(@playersInfo, @records) bewirkt, dass
das Array playersInfo befüllt wird und die Anzahl der Einträge wird in "records" abgelegt
Also darf eine Schleife doch immer nur von 0 bis records-1 laufen.
Niemals darf die Schleife über das gesamte reservierte Array laufen!!
playersInfo[0] bis playersInfo[records-1] enthalten gültige Daten.
playersInfo[records] bis playersInfo[1024] enthalten ungültige Daten.
Delphi-Quellcode:
if Player[i].id = Id then
      result := pchar(player[i].Name);
//Die Schleife läuft weiter weil ja mehrere Sprechen können, und ich mich der sich auch af dem channel befindet nicht angezeigt haben möchte, sprich ich und noch jemand sprechen gleichzeitig, dann brauche ich nur seine ID und nicht meine
Das macht so alles keinen Sinn, weil der Zeiger "Result" ständig neu überschrieben wird.
Wenn ich nur einen Sprecher suchen möchte, dann kann die Schleife mit "break" doch beendet werden.
Wenn ich mehrere Sprecher haben möchte, dann geht das nicht mit PCHAR.

Hier ein Beispiel, das Sinn machen würde:
Delphi-Quellcode:
// wichtig in diesem Beispiel ist, dass Result ein String ist
// nur so können alle Sprecher (ausser mir selbst) in einem String zurückkommen
for i:= 0 to records-1 do
begin
  if Player[i].id <> MeineEigeneID then
  begin
    Result := Result + Player[i].Name+ ' | ';
  end;
end;

Sir Rufo 5. Dez 2008 15:17

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Zitat:

Zitat von shmia
Delphi-Quellcode:
for i:= 0 to high(Player) do // Record wurde ja auf 1024 begrenzt, bzw werden wohl nicht mehr als 1024 player online sein oder dürfen laut TS?

Wo das denn :gruebel:

Ich dachte das ist so definiert
Delphi-Quellcode:
type Player_ = record
      ID : integer;
      Name : string;
      end;


var Player : array of player_;
... und war das nicht so:
Delphi-Quellcode:
var
  VarArray : array [0..128] of integer;
das High( VarArray ) auch 128 liefert :gruebel:

und das hier
Delphi-Quellcode:
if Player[i].id = Id then
      result := pchar(player[i].Name);
//Die Schleife läuft weiter weil ja mehrere Sprechen können, und ich mich der sich auch af dem channel befindet nicht angezeigt haben möchte, sprich ich und noch jemand sprechen gleichzeitig, dann brauche ich nur seine ID und nicht meine
da wird Result doch nicht ständig überschrieben, denn der Wert von ID ändert sich in der Schleife nicht und daher gibt es nur eine ID wo das zutrifft, also auch nur einmal Aufrufen.

SimStar001 5. Dez 2008 15:36

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Zitat:

und war das nicht so:
Delphi-Quellcode: markieren
var
VarArray : array [0..128] of integer;


das High( VarArray ) auch 128 liefert Grübelnd...

NEIN high liefert den Höchsten Index der übergebenen Variable! in dem Fall 127!!!


So ich habe mal noch die Unterfunktion DoGetSpeakers überarbeitet, ich denke da war ein denkfehlr drin!


Delphi-Quellcode:
function DoGetSpeakers : pchar;
var
  IDs : Array[0..1023] of Integer;
  Records : Integer;
  I, u: integer;
  PlayersInfo : Array[0..1023] of TtsrPlayerInfo;
  ID : integer;
begin
  result := '';
  Records := 1024;
  try
 if not DisplayResult(tsrGetSpeakers(@playersInfo, @records) ) then exit;
  //if Records > 0 then ;
  for I :=0 to Records-1 do
    begin
    ID := PlayersInfo[i].PlayerID ;

    for u := 0 to high(Player) do
      if Player[u].id = Id then
        begin
        result := pchar(player[u].Name);
        break;
        end;
    end;

  except
    On E:Exception Do
        hLog.AddException(E);
        end;
end;

ich werde weiter testen und mir den ganzen code nochmal in ruhe ansehen und verbessern!

DeddyH 5. Dez 2008 15:42

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Bei einem array[0..128] wäre der höchste Index doch 128, Length() wäre 129, oder?

SimStar001 5. Dez 2008 15:52

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Ja stgimmt, wenn man es so definert! fehler meinerseits! sry


So Code wurde leicht verändert und wird jetzt getestet:

Delphi-Quellcode:
function GetTSSpeaker : pchar;
Function DisplayResult( Res : Integer ) : Boolean;
Var
  ErrorMessage: array[0..1023] of Char;
begin
  if res = 0 then
    begin
    //Writeln('OK');
    Result := True;
    exit;
    end
      else
        begin
        tsrGetLastError(@ErrorMessage, SizeOf(ErrorMessage));
        Result := False;
        end;
end;

function DoGetPlayers : boolean;
var
  PlayersInfo : Array[0..1023] of TtsrPlayerInfo;
  Records : Integer;
  I : integer;
begin
  result := true;
  Records := 1024;
  try
  DisplayResult(tsrGetPlayers(@playersInfo, @records) );

  setlength(Player,records);

  if records > 0 then
    begin
    for I := 0 to Records - 1 do
      begin
      PLayer[i].id := PlayersInfo[i].PlayerID;
      Player[i].Name := PlayersInfo[i].NickName;
      end;
    result := true;
    end;

    except
    On E : Exception Do
        begin
        hLog.AddException(E);
        exit;
        end;
    end; // End Try Abschnitt
end;

function DoGetSpeakers : pchar;
var
  IDs : Array[0..1023] of Integer;
  Records : Integer;
  I , u: integer;
  PlayersInfo : Array[0..1023] of TtsrPlayerInfo;
  ID : integer;
begin
  result := '';
  Records := 1024;
  try
  DisplayResult(tsrGetSpeakers(@playersInfo, @records) );
  //if Records > 0 then ;
  for I := 0 to Records - 1 do
    for u := 0 to high(Player) do
      if Player[u].id = PlayersInfo[i].PlayerID then
        begin
        result := pchar(player[u].Name);
        break;
        end;


    except
    On E : Exception Do
        hLog.AddException(E);
    end;  //Ende Try Abschnitt
end;

begin
  result := '';
  if DOGetPlayers then
    try
    result := DogetSpeakers;
      except
        On E:Exception Do
        hLog.AddException(E,'Function GetTSSpeaker', []);
        end;
end;

Sir Rufo 5. Dez 2008 17:00

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Zitat:

Zitat von SimStar001
Zitat:

und war das nicht so:
Delphi-Quellcode: markieren
var
VarArray : array [0..128] of integer;


das High( VarArray ) auch 128 liefert Grübelnd...

NEIN high liefert den Höchsten Index der übergebenen Variable! in dem Fall 127!!!

Dann ist mein Delphi kaputt, denn
Delphi-Quellcode:
var MeinArray : array[ 0..128] of integer;
begin
  ShowMessage( Format( 'low: %d, high: %d', [ Low( MeinArray ), High( MeinArray ) ] ) );
end;
Liefert mir "low: 0, high: 128"

Edit:

Puh, da habe ich aber Glück, mein Delphi ist doch nicht kaputt. Laut OH wird bei einem normalen Array (array[n..m]) mit High der höchste Index zurückgeliefert (also m) und mit Low der niedrigste (also n).
Bei einem offnen Array liefert High die Anzahl der Elemente - 1

SimStar001 5. Dez 2008 17:04

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
So nun kam endlich mal der Fehler:

Dies ist die Meldung:
http://xero-network.eu/~simstar/Fehler.jpg

Die Fehlerhafte Code Zeiler ist Diese:


Delphi-Quellcode:
function DoGetSpeakers : pchar;
var
  IDs : Array[0..1023] of Integer;
  Records : Integer;
  I , u: integer;
  PlayersInfo : Array[0..1023] of TtsrPlayerInfo;
  ID : integer;
begin
  result := '';
  Records := 1024;
  try

  // >>>>>>>>>>>>>>>>>>>>FEHLER!<<<<<<<<<<<<<<<<<<<<<
  DisplayResult(tsrGetSpeakers(@playersInfo, @records) );
  //>>>>>>>>>>>>>>>>>>>>>FEHLER!<<<<<<<<<<<<<<<<<<<<<

  //if Records > 0 then ;
  for I := 0 to Records - 1 do
    for u := 0 to high(Player) do
      if Player[u].id = PlayersInfo[i].PlayerID then
        begin
        result := pchar(player[u].Name);
        break;
        end;


    except
    On E : Exception Do
        hLog.AddException(E);
    end;  //Ende Try Abschnitt
end;
In die TSRemote.dll kann man nicht reinschauen, wird von TS geliefert!

SO ich weiß nicht woran der Fehler liegt!

//


Ich weiß, war ein lesefehler meinerseits, da du das array ja nich dynamisch erstellt hast, sondern festgelegt hast von vornherein!

steht aber auch nen beritrag weiter über deinem! :wink:

SimStar001 5. Dez 2008 20:11

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Also diese Fehlermeldung kommt immer wieder und wies auschaut kann ich da nichts gegen machen!

mkinzler 5. Dez 2008 20:19

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Diese Fehlermeldung legt nahe, dass du auf ein nichtinitialisiertes Objekt (Nil) zugreifen willst

In welcher Zeile tritt der Fehler den genau auf?

Hawkeye219 5. Dez 2008 20:31

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Hallo,

liefert die Funktion tsrGetSpeakers wirklich alle Informationen oder füllt sie das übergebene Array nur mit IDs? Die Beschreibung der Schnittstelle in diesem Beitrag lässt auf letzteres schließen.

Gruß Hawkeye

SimStar001 5. Dez 2008 20:51

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Danke für den Link, ich glaube genau das problem habe ich auch!

kann es vielleicht auch daran liegen wie dort geschireben wurde?

Zitat:

Moin Sko,

ich würde den Timer zu Beginn der OnTimer-Routine ab-, und nach der Abarbeitung wieder einschalten. (so ähnlich hab' ich das heute doch schon 'mal geschrieben Grübelnd... Wink)

Delphi-Quellcode: markieren
begin
PopupTimer.Enabled := false;
try
// hier der eigentliche Code für die OnTimer Routine
finally
PopupTimer.Enabled := true;
end;
end;


Damit verhinderst Du, dass die Routine erneut aufgerufen wird, bevor sie abgearbeitet wurde.
Es könnte gut sein, dass die Routine länger als eine Sekunde braucht...

Ich werde diese Lösung zumindest erstmal mit einbeziehen und dann weiter testen und natürlich die TSRemote.dll die dort zur verfügung steht nutzen!

Zur zeit läuft das programm mal wieder seit mehr als 20 mins stabil ohne fehler!? :gruebel:

Blup 8. Dez 2008 09:30

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Delphi-Quellcode:
type Player_ = record
      ID : integer;
      Name : string;
      end;

var Player : array of player_;

function DoGetSpeakers : pchar;
  {...}
        result := pchar(player[u].Name);
Ich vermute die Fehlerursache ist bei der Verwendung von PChar zu suchen.
Dynamische Arrays können unter Umständen im Speicher verschoben werden, insbesondere wenn sich die Anzahl der Elemente vergrößert.
Den Rückgabewert unbedingt auf String ändern. Prüfen, wo es noch ähnlichen Schwachstellen gibt.
Zugriffsverletzungen treten leider nicht immer dort auf, wo diese verursacht werden.

SimStar001 17. Jan 2009 08:41

Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
 
Das problem liegt darin, dass ich den rueckgabewert leider nicht aendern kann, da die funktion in der TSRemote.dll liegt, auf die iach keinen einfluss habe... oder gibt es noch eine andere moeglichkeit?


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:50 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