Thema: Delphi Unicode-Umwandlung

Einzelnen Beitrag anzeigen

Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#16

Re: Unicode-Umwandlung

  Alt 12. Aug 2007, 11:22
Hi,
Dein Code ist so nicht wirklich sauber. Du gibst hier einen Zeiger auf einen Speicherbereich zurück, von dem Du nicht weißt wie lang dieser gültig ist.
Am deutlichsten kann man das an einem Beispiel machen:

Delphi-Quellcode:
function doFoo: PWideChar;
var s: String;
begin
  s := #$53#$30#$8C#$30$00$00;
  result := unicode(s);
end;

procedure doBar;
var p: PWideChar;
begin
  p := doFoo;
  // und hier knallt es dann beim Zugriff auf p
end;
Der Zeiger, den Unicode liefert, der zeigt in doFoo, nach dem Aufruf von unicode(s) noch auf das erste Element von s. Wird die Funktion verlassen, wird s durch Delphi frei gegeben, das Ergebnis der Funktion zeigt aber weiterhin auf diesen Speicher. In doBar steht jetzt eine Adresse zur Verfügung, die ins Daten-Nirvana zeigt. Mit etwas Glück bekommst Du nur eine Zugriffsverletzung, da Delphi erkennt, dass Du auf ungültigen Speicher zugreifst. Mit etwas Pech liest/schreibst Du zufällig irgendwo in den Speicher (Deines Programms) und hast ein undefiniertes Verhalten. Dieses Verhalten kann sich bei jedem Aufruf völlig anders verhalten (je nachdem was gerade wo im Speicher steht und was Du zufällig überschreibst), solche Fehler sind deswegen sehr schwer zu finden!

Besser ist es deshalb, wenn Du in der Methode einen neuen Speicherbereich allozierst und dessen Adresse zurückgibst. Wichtig ist es dann, dass Du auch für die Freigabe sorgen musst (aber bis zur expliziten Freigabe wäre die Adresse gültig!).

Delphi-Quellcode:
function unicode(inp: string): PWideChar;
begin
  GetMem(result, length(inp));
  Move(inp[1], result, length(inp));
end;

procedure TForm1.Button1Click(Sender: TObject);
var ustr: PWideChar;
begin
  ustr := unicode(#$53#$30#$8C#$30#$6F#$30#$5E#$97#$38#$5E#$6B#$30#$ED#$77#$44#$30#$C6#$30#$AD#$30#$B9#$30#$C8#$30#$67#$30#$42#$30#$8B#$30#$02#$30#$2E#$00#$69#$00#$64#$00#$78#$00);
  movefilew('testa', ustr);
  FreeMem(ustr); // erst hier wird ustr ungültig
end;
Das Ydobon eigentlich meinte (gerade mal gelesen) war sicherlich, dass Du im gleichen Scope wie der String (also ohne Aufruf der Funktion unicode) diesen Cast hättest durchführen können, auch das ist natürlich möglich:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var ustr: PWideChar;
begin
  ustr := #$53#$30#$8C#$30#$6F#$30#$5E#$97#$38#$5E#$6B#$30#$ED#$77#$44#$30#$C6#$30#$AD#$30#$B9#$30#$C8#$30#$67#$30#$42#$30#$8B#$30#$02#$30#$2E#$00#$69#$00#$64#$00#$78#$00;
  movefilew('testa', PWideChar(@ustr[1]));
end;
Hier ist die Adresse für den Aufruf von movefilew gültig, da die aufgerufene Methode synchron arbeitet. Kritisch wäre das erst, wenn Du hier eine asynchrone Methode hast, die also parallel abgearbeitet wird und vor der vollständigen Bearbeitung zurückkehrt.

Gruß Der Unwissende
  Mit Zitat antworten Zitat