Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi TComPort: Zugriffsverletzung beim Senden eines Strings (https://www.delphipraxis.net/164211-tcomport-zugriffsverletzung-beim-senden-eines-strings.html)

Schulze 2. Nov 2011 18:21

TComPort: Zugriffsverletzung beim Senden eines Strings
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo!

Ich nutze schon länger dieses Forum als Datenbank für Tipps und Codeschnipsel und es hat mir schon oftmals geholfen. Doch nun bin ich einmal mehr mit meinem Latein am Ende und finde keine Lösung dazu. Jetzt hoffe ich auf eure Hilfe.

Es geht um ein kleines Programm, welches einen digitalen Druckkalibrator (quasi eine Luftpumpe mit hochgenauem Drucksensor) fernsteuert. Es sind nicht viele Funktionen dazu notwendig. Es werden lediglich Befehle für "Sollwert setzen", "Auf Sollwert pumpen" und "Entlüften" über die Serielle Schnittstelle gesendet. Bis auf "Sollwert setzen" sind die Befehle statisch und für die Kommunikation nutze ich die TComPort von Dejan Crnila, wenn auch nicht die neuste Version, aber sie funktioniert.

Die statischen Befehle lassen sich ohne Probleme senden, lediglich bei dem Befehl zum Setzen des Solldrucks, bei dem der Inhalt eines Textfeldes (String zu Integer, mit 10 multiplizieren und wieder zurück zum String) in den zu sendenden String mit eingebaut werden muss, stürzt das Programm nach dem 2. 0der 3. Senden des Befehles mit einer Zugriffsverletzung ab.

Statischer Befehl:
Delphi-Quellcode:
if ComPort.Connected then begin
  Str := ':ps 0 ' + #13;
  ComPort.WriteStr(Str);
  Status.Panels[0].Text := Str;
end;
Der Befehl zum Senden des Solldruckes:
Delphi-Quellcode:
 if ComPort.Connected then begin
  TempVal := StrToFloat(EditSW.Value)*10;
  TxStr := ':pr ' + FloatToStr(TempVal) + #13;
  Status.Panels[0].Text := TxStr; // Debugging-Infos ausgeben
  ComPort.WriteStr(TxStr);
EditSW ist ein JvValidateEdit, das einen Double ausgibt. Die komplette Umwandlung und Umrechnung scheint problemlos von Statten zu gehen. Wenn ich ComPort.WriteStr() in diesem Code auskommentiere, so wird der Befehl korrekt in der Statusleiste beliebig oft angezeigt. Nach dem Verbinden mit dem COM (Sende-Befehl nicht auskommentiert), lässt sich der Befehl beim ersten Mal korrekt senden, wobei bereits in der Statusanzeige, welche noch vor dem Senden geändert wird, nur ":pr" steht, anstatt wie gewöhnlich ":pr 0". Im Terminal (0-Modemkabel zwischen 2 COMs) wird der Befehl korrekt angezeigt. Nach dem 2. Senden (Ebenfalls korrekt im Terminal) erscheint die folgende Fehlermeldung, ohne Ausführen über die IDE schließt das Programm einfach:
Anhang 35472

Durch Auskommentieren und Ausprobieren habe ich mittlerweile herausgefunden, dass SendStr vom TComPort ein Problem mit zusammengesetzten Strings hat.

Beispiel:
Delphi-Quellcode:
// Funktioniert:
Str := ':ps ' + '0' + #13;
ComPort.WriteStr(Str);

//Funktioniert nicht und stürzt mit einer Access Violation ab:
Str2 := '0';
Str := ':ps 0' + Str2 + #13;
ComPort.WriteStr(Str);
Ich nutze Delphi 6 und TComPort 3.0.
Kann jemand den Fehler nachvollziehen oder reproduzieren?

Vielen Dank für eure Hilfe im Vorraus!

Grüße,
Sebastian


Edit: Wenn ich TxString mit Copy() in einen anderen String kopiere, lässt sich eben jener String problemlos senden.

Schulze 5. Nov 2011 21:05

AW: TComPort: Zugriffsverletzung beim Senden eines Strings
 
Also, durch das Kopieren des zu sendenden Strings mittels Copy() in einen neuen String konnte ich auf meinem Rechner das Programm zum laufen bekommen. Auf einem anderen Rechner jedoch tritt der Fehler erneut auf.

Furtbichler 6. Nov 2011 10:24

AW: TComPort: Zugriffsverletzung beim Senden eines Strings
 
Ich glaube nicht, das Du das Problem korrekt eingekreist hast. Es mag sein, das der Austausch (oder Weglassen) der Stringkonkatenation den Fehler provoziert oder unterdrückt, aber das das SendStr in beiden Fällen identisch aufgerufen wird, liegt der Fehler woanders.

Bummi 6. Nov 2011 10:58

AW: TComPort: Zugriffsverletzung beim Senden eines Strings
 
:thumb:

Schulze 6. Nov 2011 15:53

AW: TComPort: Zugriffsverletzung beim Senden eines Strings
 
Das ist es ja, was mich verwirrt, ich rufe das WriteStr absolut identisch auf, aber bei einem aus 2 Strings zusammengesetzten String tritt der Fehler auf, allerdings kann ich keine weitere Ursache oder eine andere Eingrenzung dafür finden.

himitsu 6. Nov 2011 16:01

AW: TComPort: Zugriffsverletzung beim Senden eines Strings
 
Delphi-Quellcode:
// 1
Str := ':ps ' + '0' + #13;

// 2
Str2 := '0';
Str := ':ps 0' + Str2 + #13;
1: Der Compiler ist so schlau und macht aus den drei Stringkonstanten eine Stringkonstante ... zur Laufzeit wird da nichts mehr gemacht, also bleibt das, von der Speicherverwalung her, eine Konstande

2: Da werden Strings verbunden, also entsteht eine eine neue Variable.

Das Write schrottet jetzt irgendwie den Speicher, was bei der Konstante wohl keine großen Auswirkungen zeigt,
da bei Freigabe des Variablenzeigers kein Eingriff des Speichermanagements eintritt.
Aber bei der Variable wird das Speichermanagement so geschrottet, daß es danach in einem Fehler endet.

Furtbichler 6. Nov 2011 16:29

AW: TComPort: Zugriffsverletzung beim Senden eines Strings
 
So sieht der Code im aktuellen TComport aus.
Delphi-Quellcode:
// perform asynchronous write operation
function TCustomComPort.WriteStrAsync(const Str: string; var AsyncPtr: PAsync): Integer;
var sa : Ansistring;
begin
  if Length(Str) > 0 then
  begin
    sa := AnsiString(str);
    Result := WriteAsync(Sa[1], Length(Str), AsyncPtr)
  end
  else
    Result := 0;
end;
// perform synchronous write operation
function TCustomComPort.WriteStr(const Str: string): Integer;
var
  AsyncPtr: PAsync;
begin
  InitAsync(AsyncPtr);
  try
    WriteStrAsync(Str, AsyncPtr);
    Result := WaitForAsync(AsyncPtr);
  finally
    DoneAsync(AsyncPtr);
  end;
end;
Bringt uns das weiter?

ConnorMcLeod 6. Nov 2011 16:47

AW: TComPort: Zugriffsverletzung beim Senden eines Strings
 
Zitat:

Zitat von Schulze (Beitrag 1134117)
Delphi-Quellcode:
// Funktioniert:
Str := ':ps ' + '0' + #13;
ComPort.WriteStr(Str);

Ergebnis: ':ps 0'#13

Zitat:

Zitat von Schulze (Beitrag 1134117)
Delphi-Quellcode:
//Funktioniert nicht und stürzt mit einer Access Violation ab:
Str2 := '0';
Str := ':ps 0' + Str2 + #13;
ComPort.WriteStr(Str);

Ergebnis: ':ps 00'#13

Ist es vllt dieser kleine Unterschied?

Schulze 6. Nov 2011 17:29

AW: TComPort: Zugriffsverletzung beim Senden eines Strings
 
@ConnorMcLeod:
Falls Du damit meinst, dass es einmal eine Null und dann zwei Nullen sind: Das ist ein kleiner Flüchtigkeitsfehler meinerseits. Obs nun 1 oder 2 Nullen werden spielt für die (Nicht-)Funktion keine Rolle. Es diente lediglich der Veranschaulichung, welche Kombination funktioniert und welche nicht.

ConnorMcLeod 6. Nov 2011 18:34

AW: TComPort: Zugriffsverletzung beim Senden eines Strings
 
Ja, habe ich gemeint; könnte ja sein, dass Datenbits/Stopbits so eingestellt sind, dass es ein Thema wird.

Ich verwende D2010, TComPort v.4 und com0com für dieses Beispiel und es funkt problemlos:
Delphi-Quellcode:
var
  ComPort: TComPort;
  Str, Str2: string;
begin
  ComPort := TComPort.Create(Self);
  try
    Str2 := '0';
    Str := ':ps 0' + Str2 + #13;
    ComPort.Port := 'CNCA0';
    ComPort.Open;
    ComPort.WriteStr(Str);
  finally
    FreeAndNil(ComPort);
  end;
end;
Schau doch mal mit einem Breakpoint auf ComPort.WriteStr und [F7], wo und warum es kracht.


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