AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Cast Array[0..x] of Byte in TBytes

Ein Thema von schwa226 · begonnen am 29. Jun 2011 · letzter Beitrag vom 30. Jun 2011
Antwort Antwort
Seite 1 von 3  1 23      
schwa226

Registriert seit: 4. Apr 2008
400 Beiträge
 
#1

Cast Array[0..x] of Byte in TBytes

  Alt 29. Jun 2011, 18:39
Hi!

Ich möchte gerne mit TIdTCPServer Daten an den Client schicken.
Über
AContext.Connection.IOHandler.Write(Buffer, len); Kann ich TBytes an den Client schicken.

Ich habe aber nun Buffer als Array[0..1023] of Byte;

Nun will Write den Buffer nicht mehr. Und extra immer ein TBytes Array mit Setlength zu setzen, dann die Daten kopieren und diese dann zu schicken ist etwas umständlich.

Wie kann man das richtig Casten damit es keine Probleme gibt?
Delphi 2010, Update 4 & 5
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#2

AW: Cast Array[0..x] of Byte in TBytes

  Alt 29. Jun 2011, 19:01
Wie kann man das richtig Casten damit es keine Probleme gibt?
Das kann man nicht casten, da es sich um unterschiedliche Datentypen handelt, die auch ein unterschiedliches Speicherlayout haben.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
schwa226

Registriert seit: 4. Apr 2008
400 Beiträge
 
#3

AW: Cast Array[0..x] of Byte in TBytes

  Alt 29. Jun 2011, 20:53
Ok, danke!

So gibt es zumindest keinen Crash:
Delphi-Quellcode:
var
  _buffer : TBytes;
  buffer : Array[0..1023] of Byte;
begin

  SetLength(_buffer, Length(buffer));
  _buffer := @buffer[0];
Man spart sich das Memcopy.
Delphi 2010, Update 4 & 5
  Mit Zitat antworten Zitat
Satty67

Registriert seit: 24. Feb 2007
Ort: Baden
1.566 Beiträge
 
Delphi 2007 Professional
 
#4

AW: Cast Array[0..x] of Byte in TBytes

  Alt 29. Jun 2011, 21:03
Das kann nicht richtig sein.

Du verlierst den Zeiger auf den dynamisch reservierten Speicher (_buffer). Es sollte ein Speicherleck geben und fast eine Zugriffsverletzung, wenn _buffer irgendwann freigegeben werden soll und buffer kein gültiger Zeiger mehr ist.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#5

AW: Cast Array[0..x] of Byte in TBytes

  Alt 29. Jun 2011, 21:06
So gibt es zumindest keinen Crash:
Delphi-Quellcode:
var
  _buffer : TBytes;
  buffer : Array[0..1023] of Byte;
begin

  SetLength(_buffer, Length(buffer));
  _buffer := @buffer[0];
Man spart sich das Memcopy.
Na toll! Man baut sich eine Zeitbombe ein, nur um ein MemCopy zu sparen? Schreib doch besser eine Funktion, die dir aus einem statischen Array ein TBytes macht und der Code wird wesentlich sauberer, lesbarer und weniger fehleranfällig.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Thom

Registriert seit: 19. Mai 2006
570 Beiträge
 
Delphi XE3 Professional
 
#6

AW: Cast Array[0..x] of Byte in TBytes

  Alt 30. Jun 2011, 00:08
Das kann man nicht casten, da es sich um unterschiedliche Datentypen handelt, die auch ein unterschiedliches Speicherlayout haben.
Da muß ich leider widersprechen: Auch wenn es sich im programmtechnischen Sinn um verschiedene Typen handelt (dynamisches vs. statisches Array), so liegen dennoch in beiden Fällen die Daten byteweise hintereinander. Damit haben sie sehr wohl das selbe Speicherlayout.

Durch den Umstand, daß die Write-Methode den Parameter ABuffer als Konstante erwartet, wird vom Compiler nur die Anfangsadresse des Arrays übergeben. Und damit ist es völlig egal, ob es sich dabei um den Beginn eines dynamischen oder eines statischen Arrays handelt.

Ein kleines Beispiel:
Delphi-Quellcode:
procedure Test(const ABuffer: TBytes; ALength: Integer);
var
  n: Integer;
  s: String;
begin
  s:='';
  for n:=0 to ALength-1 do
  begin
    if s<>''
      then s:=s+',';
    s:=s+IntToStr(ABuffer[n]);
  end;
  ShowMessage(s);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  n: Integer;
  a: array[0..9] of Byte;
  b: TBytes;
begin
  //dynamisches Array:
  SetLength(b,10);
  for n:=Low(b) to High(b) do
    b[n]:=n;
  Test(b,10);
  //statisches Array:
  for n:=Low(a) to High(a) do
    a[n]:=n;
  Test(TBytes(@a[0]),10); //<- Typecast
end;
Das heißt: Ein Typecast ist sehr wohl möglich. Ob er auch sinnvoll ist, steht auf einem ganz anderen Blatt...
Thomas Nitzschke
Google Maps mit Delphi

Geändert von Thom (30. Jun 2011 um 00:11 Uhr)
  Mit Zitat antworten Zitat
schwa226

Registriert seit: 4. Apr 2008
400 Beiträge
 
#7

AW: Cast Array[0..x] of Byte in TBytes

  Alt 30. Jun 2011, 07:50
Nur zum Beruhigen: ich habe es so eh nicht umgesetzt!
Bei meinen Versuchen war das die einzige Methode wo es keinen Memory Fehler gab
Delphi 2010, Update 4 & 5
  Mit Zitat antworten Zitat
Satty67

Registriert seit: 24. Feb 2007
Ort: Baden
1.566 Beiträge
 
Delphi 2007 Professional
 
#8

AW: Cast Array[0..x] of Byte in TBytes

  Alt 30. Jun 2011, 08:25
@schwa266: Sowas hat jeder mal versucht, besonders wenn man die Verwandschaft (und Compiler-Unterstützung) von String und PChar kennt, will man das gerne mal auf andere Bereiche übertragen.

Ein Typecast ist sehr wohl möglich. Ob er auch sinnvoll ist
Ein Typecast ist mit einem untypisierten Pointer immer möglich, die Frage ist nicht ob er sinnvoll ist, sondern ob er richtig ist:

Delphi-Quellcode:
procedure Test(ABuffer: TBytes; ALength: Integer);
var
  n: Integer;
  s: String;
begin
  ShowMessage(Format('From %d To %d', [Low(ABuffer), High(ABuffer)]));
"From 0 To <Random>"
Wie das Beispiel zeigt ist der Typecast nicht korrekt und nur im begrenzten Fall problemlos.

Geändert von Satty67 (30. Jun 2011 um 08:27 Uhr)
  Mit Zitat antworten Zitat
Thom

Registriert seit: 19. Mai 2006
570 Beiträge
 
Delphi XE3 Professional
 
#9

AW: Cast Array[0..x] of Byte in TBytes

  Alt 30. Jun 2011, 11:58
@Satty67:

Ich hatte auf die Behauptung von Uwe Raabe reagiert - nicht auf Deine. Und es ging bei der Frage des Threaderstellers darum, ob es in dem konkteren Fall möglich ist.

Noch einmal ausführlich für Dich, was ich mit meiner Bemerkung gemeint hatte:

Selbstverständlich ist es eine bekannte Tatsache, daß ein Pointer ein Pointer bleibt und der Typecast nur ein (unsauberes) Mittel ist, um den Compiler dazu zu bringen, seine Arbeit ohne Fehlermitteilung fortzusetzen. Man muß also sehr genau wissen, was man tut und sich überlegen, welche Delphi-Funktionen mit dem gecasteten Pointer eingesetzt werden können.
Genau aus diesem Grund hatte ich geschrieben, daß man sich die Frage stellen sollte, ob ein Cast sinnvoll ist - also ob er das gewünschte Ergebnis liefert. Geht es zum Beispiel um eine hohe Geschwindigkeit, wäre das ständige Kopieren von Puffern kontraproduktiv.
Natürlich wäre es günstiger - falls möglich - , das statische Array gleich durch ein dynamisches Array zu ersetzten und damit potentiellen Problemen aus dem Weg zu gehen.

Hatte ich an irgend einer Stelle behauptet, daß ein derartiger Cast immer und in jedem Fall sinnvoll ist? Ich kann mich nicht daran erinnern.
Es ist also von Dir absolut überflüssig, in einer derart belehrenden Art und Weise zu schreiben und andere für dumm zu halten.
Aber das scheint hier im Forum leider eine weit verbreitete Unsitte zu sein. Da wird nicht auf konkrete Fragen geantwortet sondern lieber aus - nahezu - jedem Thread eine Prizipiendiskussion gemacht, um sich selbst zu profilieren. Sehr bezeichnend und sehr bedauerlich.
Thomas Nitzschke
Google Maps mit Delphi
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#10

AW: Cast Array[0..x] of Byte in TBytes

  Alt 30. Jun 2011, 13:32
Auch wenn es sich im programmtechnischen Sinn um verschiedene Typen handelt (dynamisches vs. statisches Array), so liegen dennoch in beiden Fällen die Daten byteweise hintereinander. Damit haben sie sehr wohl das selbe Speicherlayout.
Das gilt sicher für die Nutzdaten, nicht aber für die Länge des Arrays und die Referenzzählung. Selbst wenn das im aktuellen Fall nicht relevant sein sollte, besteht immer die Gefahr, das dieses Konstrukt in einer zukünftigen Version nicht mehr funktioniert.

Das tatsächliche Speicherlayout kann man hier nachlesen. Das dynamische Array ist also ein Pointer auf die Nutzdaten, wobei der Bereich vor den Nutzdaten aber noch zum Array gehört. Demnach ist der Cast auf das statische Array einfach nur brandgefährlich, weil die 8 Byte vor dem Array nun als Größe und als Referenzzähler interpretiert werden. In dem Längenfeld kann alles möglich drinstehen und es kann sich sogar jederzeit ändern - heißt: die verwendete Länge passt nicht zur wirklichen Größe des Arrays. Dann kann es auch noch passieren, daß der Compiler dann noch bei der Referenzzählung das Array einfach frei gibt (das wird spaßig). Wenn es nicht crasht ist das einfach nur Glück.

Beiliegendes Projekt zeigt das ganz deutlich - und es crasht auch beim Beenden.

Insofern bleibe ich bei meiner Aussage, daß das Speicherlayout unterschiedlich ist.
Angehängte Dateien
Dateityp: zip Projekt88.zip (1,2 KB, 16x aufgerufen)
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


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 11: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