![]() |
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 |
Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
Wo und wie ist Player deklariert?
|
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_; |
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; |
Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
tsrGetSpeakers(@playersInfo, @records)
??? |
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: |
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
|
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?
|
Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
Öhm, Jens:
Zitat:
|
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; |
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:
Was den rest betrifft, habe ich den code auch wenn er scheinbar nichts macht stehengelassen!
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 PS: Programm wird gerade getestet! |
Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
Delphi-Quellcode:
der Aufruf von tsrGetSpeakers(@playersInfo, @records) bewirkt, dass
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?
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:
Das macht so alles keinen Sinn, weil der Zeiger "Result" ständig neu überschrieben wird.
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 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; |
Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
Zitat:
Ich dachte das ist so definiert
Delphi-Quellcode:
... und war das nicht so:
type Player_ = record
ID : integer; Name : string; end; var Player : array of player_;
Delphi-Quellcode:
das High( VarArray ) auch 128 liefert :gruebel:
var
VarArray : array [0..128] of integer; und das hier
Delphi-Quellcode:
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.
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 |
Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
Zitat:
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! |
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?
|
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; |
Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
Zitat:
Delphi-Quellcode:
Liefert mir "low: 0, high: 128"
var MeinArray : array[ 0..128] of integer;
begin ShowMessage( Format( 'low: %d, high: %d', [ Low( MeinArray ), High( MeinArray ) ] ) ); end; 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 |
Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
So nun kam endlich mal der Fehler:
Dies ist die Meldung: ![]() Die Fehlerhafte Code Zeiler ist Diese:
Delphi-Quellcode:
In die TSRemote.dll kann man nicht reinschauen, wird von TS geliefert!
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; 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: |
Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
Also diese Fehlermeldung kommt immer wieder und wies auschaut kann ich da nichts gegen machen!
|
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? |
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 ![]() Gruß Hawkeye |
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:
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: |
Re: Bitte CODE prüfen - bekomme Immer eine Zugriffsverletzun
Delphi-Quellcode:
Ich vermute die Fehlerursache ist bei der Verwendung von PChar zu suchen.
type Player_ = record
ID : integer; Name : string; end; var Player : array of player_; function DoGetSpeakers : pchar; {...} result := pchar(player[u].Name); 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. |
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