Phantom-Ausgabe?

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
alfware17
Beiträge: 214
Registriert: Di 14. Dez 2010, 23:27

Phantom-Ausgabe?

Beitrag von alfware17 »

Ich habe einen merkwürdigen Effekt beobachtet. In einem (zugegeben brandneuen) Lazarus 3.60 wollte ich folgendes Programm ausführen:

UNIT Stack;

Code: Alles auswählen

{$I OsWahl.inc}

{$IFNDEF DOS} {$MODE OBJFPC} {$H+} {$ENDIF}

INTERFACE

TYPE
  PStackElement = ^TStackElement;
  TStackElement = RECORD
    Data: Pointer;
    Next: PStackElement;
  END;

  TStack = OBJECT
    Private
      Top: PStackElement;
      DataSize: Integer;
    Public
      PROCEDURE Init(SizeOfData: Integer);
      PROCEDURE Push(Data: Pointer);
      FUNCTION Pop(Data: Pointer): BOOLEAN;
      FUNCTION IsEmpty: BOOLEAN;
      PROCEDURE Clear;
  END;

IMPLEMENTATION

{$IFDEF DOS} USES DOS; {$ENDIF}

PROCEDURE TStack.Init(SizeOfData: Integer);
BEGIN
  Top := NIL;
  DataSize := SizeOfData;
END;

PROCEDURE TStack.Push(Data: Pointer);
VAR
  NewElement: PStackElement;
BEGIN
  New(NewElement);
  GetMem(NewElement^.Data, DataSize);
  Move(Data^, NewElement^.Data^, DataSize);
  NewElement^.Next := Top;
  Top := NewElement;
END;

FUNCTION TStack.Pop(Data: Pointer): BOOLEAN;
VAR
  TempElement: PStackElement;
BEGIN
  IF Top = NIL THEN
    Pop := FALSE
  ELSE BEGIN
    Move(Top^.Data^, Data^, DataSize);
    TempElement := Top;
    Top := Top^.Next;
    FreeMem(TempElement^.Data, DataSize);
    Dispose(TempElement);
    Pop := TRUE;
  END;
END;

FUNCTION TStack.IsEmpty: BOOLEAN;
BEGIN
  IsEmpty := Top = NIL;
END;

PROCEDURE TStack.Clear;
VAR
  TempElement: PStackElement;
BEGIN
  WHILE Top <> NIL DO BEGIN
    TempElement := Top;
    Top := Top^.Next;
    FreeMem(TempElement^.Data, DataSize);
    Dispose(TempElement);
  END;
END;

BEGIN
END.

PROGRAM MyStack;

{$IFNDEF DOS} {$MODE OBJFPC} {$H+} {$ENDIF}

USES
  Stack, Stdio;

TYPE
  TData = RECORD
    DataString: STRING[50];
    DataInt: INTEGER;
  END;

VAR
  BStack: TStack;
  BData: TData;

BEGIN
  BStack.Init(SizeOf(TData));

  BData.DataString := 'Element 1';
  BData.DataInt := 100;
  BStack.Push(@BData);

  BData.DataString := 'Element 2';
  BData.DataInt := 200;
  BStack.Push(@BData);

  BData.DataString := 'Element 3';
  BData.DataInt := 300;
  BStack.Push(@BData);

  WHILE NOT BStack.IsEmpty DO BEGIN
    IF BStack.Pop(@BData) THEN
      WriteLn('Gepoppt: ', BData.DataString, ' - ', BData.DataInt);
  END;

  BStack.Clear;

  Readln;

END.
Auf meinem Laptop mit dem besagten Lazarus 3.60 kam kurz nach dem readln noch eine Ausgabe, irgendwas mit "Verarbeitung..." und zweizeilig. DIe war aber so schnell weg und ich konnte sie beim besten Willen nicht lesen. Ich glaube, ich konnte das nachstellen, ich glaube aber auch langsam an weiße Mäuse die ich da gesehen habe. Zumal mein Lazarus 2.26 hier am PC nichts dergleichen ausgibt. Und auch das eigentliche Zielsystem Turbo Pascal unter MSDOS nicht. Ich habe ein zweites readln ergänzt. Habe (unter DOS) ein writeln(memavail) ergänzt, keine Auffälligkeiten, der Heap wird sauber leer gemacht.

Nun frage ich mich, sind meine "weißen Mäuse" Grund zur Beunruhigung, habe ich generell was falsch? Ich weiß, unter FreePascal gibt es die generics und die könnte ich hier auch mal einbauen, nur nicht ohne Not weil es würde glaube ich auch das aufrufende Programm ändern. Im FPC Fall gibt es bestimmt auch einen schicken ADT Stack denn mir ein lieber Forist nennen könnte - nur muß ich eben auch eine Implementation in DOS haben...

Antworten