Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Ich und die Pointer... die nicht so wollen wie ich (https://www.delphipraxis.net/99995-ich-und-die-pointer-die-nicht-so-wollen-wie-ich.html)

turboPASCAL 20. Sep 2007 17:39


Ich und die Pointer... die nicht so wollen wie ich
 
Hi,

Delphi-Quellcode:
type
  TByteArray = array of Byte;
  PByteArray = ^TByteArray;

var
  B: PByteArray;

begin
  new(b);

  setlength(B^, 100 + 1);

  B^[10] := 255;

  writeln(B^[10]);

  dispose(B);
  readln;
end.
... das stimmt doch so oder nicht ?

Das eigentliche Problem ist das ich immer bei diesem Code eine AV erhalte:

Delphi-Quellcode:
procedure SaveBitmap32AsTGAFile(bmp32: TBitmap32; TGAFileName: String);
var
  fs: TFileStream;
  tgaHeader : TTGAFileHeader;
  DataArray: Array of DWORD;
  DataSize, n: DWORD;
begin
  ZeroMemory(@tgaHeader, sizeof(tgaHeader));
  tgaHeader.imagetype := 2;
  tgaHeader.width     := bmp32.Width;
  tgaHeader.height    := bmp32.Height;
  tgaHeader.pixeldepth := $20; // 32 Bit
  tgaHeader.descriptor := $08; // Bits 00001000 = 8 = $08

  DataSize := bmp32.Width * bmp32.Height;
  SetLength(DataArray, DataSize - 1);

  ZeroMemory(@DataArray, sizeof(DataArray));

  // Swap Bitmap top / bottom

  // >>--> AV / Berechsüberprüfung
  for n := bmp32.Width * bmp32.Height-1 downto 0 do
    DataArray[n] := bmp32.bits^[n];
  // <--<<

  fs := TFilestream.Create(TGAFileName, fmCreate);
  try
    fs.Seek(soFromBeginning, 0);
    fs.Write(tgaHeader, SizeOf(tgaHeader));
    fs.Write(DataArray[0], DataSize);
  finally
    FreeAndNil(fs);
  end;

  SetLength(DataArray, 0);
end;
Irgendwie will es nicht wie ich es will. Was ist der Fehler ?

:gruebel:

( der komplette Vorgängerquelltext )

Apollonius 20. Sep 2007 17:43

Re: Ich und die Pointer... die nicht so wollen wie ich
 
Zitat:

Delphi-Quellcode:
ZeroMemory(@DataArray, sizeof(DataArray));

Hier bewirkst du, dass du dein Array nicht mehr nutzen kann. Und beim Zugriff auf das Array knallt es natürlich. Ich glaube, du meinst
Delphi-Quellcode:
ZeroMemory(@DataArray[0], length(DataArray)*sizeof(DWord));

Khabarakh 20. Sep 2007 18:07

Re: Ich und die Pointer... die nicht so wollen wie ich
 
  • Dynamische Arrays landen auf dem Heap und sind damit automatisch genullt.
  • Die Dereferenzierung von Bits sollte unnötig sein, siehe auch das Beispiel in der Doku.
  • Was hat der obere mit dem unteren Code zu tun / Wo sind die Zeiger :stupid: ?
  • Dreht der Code das Bitmap wirklich um? Ich hätte in der Schleife einfach den n-ten mit dem (Width * Height - n)-ten Pixel getauscht, dann ist auch das zweite Array überflüssig.

Robert Marquardt 20. Sep 2007 18:15

Re: Ich und die Pointer... die nicht so wollen wie ich
 
Delphi-Quellcode:
type
  TByteArray = array of Byte;
  PByteArray = ^TByteArray;

var
  B: PByteArray;

begin
  new(b);

  setlength(B^, 100 + 1);

  B^[10] := 255;

  writeln(B^[10]);

  dispose(B);
  readln;
end.
Nein, das stimmt so nicht. Lass den PByteArray-Kram weg. SetLength regelt die Alloziierung fuer das TByteArray. Die Dealloziierung aller "array of"-Variablen geschieht heimlich und automatisch.
Delphi-Quellcode:
type
  TByteArray = array of Byte;
var
  B: TByteArray;
begin
  // Hier wird B von Delphi heimlich auf nil initialisiert
  // SetLength alloziiert 101 Elemente (Bytes).
  setlength(B, 100 + 1);

  B[10] := 255;

  writeln(B[10]);
  readln;
  // Hier gibt Delphi das alloziierte array heimlich frei
end.

turboPASCAL 20. Sep 2007 21:16

Re: Ich und die Pointer... die nicht so wollen wie ich
 
:gruebel:

Äh, nein. Ich habe mich wohl etwas schräg ausgedrückt. Der obere Teil des Codes war eine
Überlegung (so 'n kleiner Test) von mir zum unteren Code den ich Verwenden will um ein
Bitmap vertikal gespiegelt in eine TGA-Datei zu schreiben.

bmp32.bits ist ein Pointer auf ..., nein falsch ethält die Adresse eines Array of Cardinal
(DWORD).

Die Graphics32 leute haben das so gebaut:

Delphi-Quellcode:
type
  PColor32 = ^TColor32;
  TColor32 = type Cardinal;

  PColor32Array = ^TColor32Array;
  TColor32Array = array [0..0] of TColor32;
  TArrayOfColor32 = array of TColor32;
bmp32.bits ist als PColor32Array definiert.

Was ich auch Anstelle, es kommt eine AV. ( Berichs- und Überlaufüberprüfung sind an)

PS.:
Ich konnte es über "Scanline" machen, macht ja aber fasst jeder.
bmp32.FlipVert(nil); bitte nicht vorschlagen ;)

negaH 20. Sep 2007 21:34

Re: Ich und die Pointer... die nicht so wollen wie ich
 
Delphi-Quellcode:
// 1.
type
  TByteArray = array of Byte;

// 2.
  PByteArray = ^TByteArray;

// 3.
type
  TByteArray = array[MaxInt] of Byte;
  PByteArray = ^TByteArray;
beide Typdeklarationen definieren was komplett Anderes. Das 1. ist ein dynamsiches Array of Bytes. Dieses ist ein komplexer Datentyp der zwar ein Array darstellt aber intern ein Zeiger auf einen Record der ein Array enthält darstellt. Der Typ bei 2. definert also wenn man es so will einen Zeiger auf einen Zeiger.

Der Typ bei 3. ist ein Array auf Bytes mit fester Größe. Erst durch den Typ PByteArray der auf ^TByteArray referenziert ist ein Zeigertyp direkt in einen Speicherbereich der als Byte Array interpretiert werden soll. Dies ist die alte Schreibweise in der man dann auch explizit solche Speicherbereiche allozieren und deallozieren muß. Das sollte erfolgen mit GetMem() und FreeMem() aber nicht mit New() und Dispose(). Die letzeren beiden hat man verwendet um komplexere Datentypen zu allozieren/deallozieren, zb. Records oder Objekte ganz alten Typus.

Du vermischt also in deinem Code zwei komplett unterschiedliche Datentypen mit den falschen Methoden und Zugriffen darauf.
Dieses Wirrwarr entstand durch die Evolution der Delphi/PASCAL Sprache mit der Zeit.

Gruß Hagen

Khabarakh 20. Sep 2007 21:37

Re: Ich und die Pointer... die nicht so wollen wie ich
 
Welche Exception tritt denn nun auf - AV, Bereichsprüfung oder beides? Bei der Bereichsprüfung darfst du dich nicht wundern, wenn du mit einem "array[0..0]" arbeitest, am Besten also ausschalten oder - was wohl sauberer wäre - einen PColor32-Zeiger per @bmp.Bits[0] holen und dann inkrementieren.
Und wie gesagt, in der Doku fehlt die Dereferenzierung ebenfalls:
Delphi-Quellcode:
var

  P: PColor32Array;

begin

  P := Bitmap32.Bits;

  for I := 0 to Bitmap32.Width * Bitmap32.Height - 1 do

    P[I] := Gray32(Random(255)); // fill with a random grayscale noise

end;
Das sollte aber alles nicht zur AV führen. Außer dem bereits erwähnten ZeroMemory fällt mir in dem Zusammenhang nur noch eines auf: Dein DataArray ist um ein Item zu kurz.

xaromz 20. Sep 2007 21:44

Re: Ich und die Pointer... die nicht so wollen wie ich
 
Hallo,

Delphi-Quellcode:
  DataSize := bmp32.Width * bmp32.Height;
  SetLength(DataArray, DataSize - 1); // <--- Warum hier -1 ??? Damit fehlt Dir ein Element -> AV weiter unten

  ZeroMemory(@DataArray, sizeof(DataArray));
Gruß
xaromz

turboPASCAL 20. Sep 2007 22:26

Re: Ich und die Pointer... die nicht so wollen wie ich
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ja, das Setlength -1 ist ein tippfehler durch die Rumprobiererei...

Ihr könnt es ja selbst mal testen, vorrausgesetzt ihr habt dei gr32 installiert:

x000x 21. Sep 2007 00:06

Re: Ich und die Pointer... die nicht so wollen wie ich
 
Moin moin,
Khabarakh hat hier schon das Problem erkannt.
Zitat:

Zitat von Khabarakh
Bei der Bereichsprüfung darfst du dich nicht wundern, wenn du mit einem "array[0..0]" arbeitest
...
einen PColor32-Zeiger per @bmp.Bits[0] holen und dann inkrementieren.

Das sollte so funktionieren.
Delphi-Quellcode:
  // Bild "flippen"
  // >>--> AV / Berechsüberprüfung
  for n := 0 to bmp32.Width * bmp32.Height-1 do begin
       DataArray[n] := P[0];
       Inc(P);
  end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:25 Uhr.
Seite 1 von 2  1 2      

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