Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Probleme mit TStrings/TStringlist beim Freigeben (https://www.delphipraxis.net/76596-probleme-mit-tstrings-tstringlist-beim-freigeben.html)

xZise 6. Sep 2006 20:55


Probleme mit TStrings/TStringlist beim Freigeben
 
Ich habe folgenden Code geschrieben:

Delphi-Quellcode:
ShowModal;
if Files <> nil then
  Files.Free;
Files := TStringList.Create;
Problem: Es kann sein (aus unerklärenlichen Gründen), dass er (die Form wird weiterhin angezeigt), dass er in das "if Files <> nil then" springt. Weiter nicht schlimm, aber dort knallst dann:

Code:
---------------------------
Debugger Exception Notification
---------------------------
Project XXXXXXXX.exe raised exception class EAccessViolation with message 'Access violation at address 0044B150 in module 'XXXXXXXX.exe'. Read of address 00000004'. Process stopped. Use Step or Run to continue.
---------------------------
OK  Help  
---------------------------
Ich weiß leider nicht, wo das Problem sein könnte...

(Files ist deklariert :D)

Bernhard Geyer 6. Sep 2006 20:57

Re: Probleme mit TStrings/TStringlist beim Freigeben
 
Verwende mal FastMM. Der sollte dir (bei aktiven Debug und TD32-Infos) anzeigen wenn das Objekt schon irgendwo anders freigegeben wurde.

mkinzler 6. Sep 2006 21:00

Re: Probleme mit TStrings/TStringlist beim Freigeben
 
Wo steht dieser Code? (Welche Methode, welcher Klasse)

katjah 6. Sep 2006 21:23

Re: Probleme mit TStrings/TStringlist beim Freigeben
 
Läuft Dein Programm da mehrfach durch und es knallt erst beim 2. Durchlauf ?
Das liegt dann vermutlich daran, daß
Delphi-Quellcode:
Files.Free;
Files nicht auf nil setzt.

Du könntest dann stattdessen
Delphi-Quellcode:
FreeAndNil(Files)
verwenden.

xZise 6. Sep 2006 21:32

Re: Probleme mit TStrings/TStringlist beim Freigeben
 
Zitat:

Zitat von Bernhard Geyer
Verwende mal FastMM. Der sollte dir (bei aktiven Debug und TD32-Infos) anzeigen wenn das Objekt schon irgendwo anders freigegeben wurde.

Installiere ich morgen.


Zitat:

Zitat von mkinzler
Wo steht dieser Code? (Welche Methode, welcher Klasse)

Methode : Execute
Klasse : frmOp


Zitat:

Zitat von katjah
Läuft Dein Programm da mehrfach durch und es knallt erst beim 2. Durchlauf ?
Das liegt dann vermutlich daran, daß
Delphi-Quellcode:
Files.Free;
Files nicht auf nil setzt.

Du könntest dann stattdessen
Delphi-Quellcode:
FreeAndNil(Files)
verwenden.

Keine Änderung!

Kann es sein (rein theoretisch), dass während des ShowModals ein Fehler auftritt und er aber nur "if Files..." markiert?
Ich teste es mal ;)

katjah 6. Sep 2006 23:03

Re: Probleme mit TStrings/TStringlist beim Freigeben
 
Ansonsten wäre etwas mehr Code nicht schlecht.

3_of_8 6. Sep 2006 23:25

Re: Probleme mit TStrings/TStringlist beim Freigeben
 
Free funktioniert auch bei nicht instantiierten Objekten. Der Grund liegt auf der Hand.

Muetze1 7. Sep 2006 00:11

Re: Probleme mit TStrings/TStringlist beim Freigeben
 
Zitat:

Zitat von 3_of_8
Free funktioniert auch bei nicht instantiierten Objekten. Der Grund liegt auf der Hand.

Man sollte dazu aber erwähnen, dass Free nur dann ordentlich mit nicht-instanziierten Objekten funktioniert, wenn entweder eine gültige Instanzenadresse in der Variablen enthalten ist oder Nil. Bei allem anderen knallt es auch mit Free - ausser man hat ein wenig Glück und der Sprung in's Datennirvana beim Aufruf vom Destruktor landet irgendwo bei was kompatiblen...

fwsp 7. Sep 2006 00:29

Re: Probleme mit TStrings/TStringlist beim Freigeben
 
versteh ich es falsch oder könnte man nicht mit .Clear das Problem umgehen?

Bernhard Geyer 7. Sep 2006 07:14

Re: Probleme mit TStrings/TStringlist beim Freigeben
 
Zitat:

Zitat von fwsp
versteh ich es falsch oder könnte man nicht mit .Clear das Problem umgehen?

Für diesen 3-Zeiler allein: Ja. Aber das Problem liegt doch woanders das Files eine ungültige Referenz darstellt. Und dann Knallt es auch bei Clear.

oki 7. Sep 2006 08:24

Re: Probleme mit TStrings/TStringlist beim Freigeben
 
Hi,

dieses Problem kenne ich auch. Du hast die Instanz von Files an einer anderen Stell oder in einem vorherigen Durchlauf zerstört. Wenn Du das mit Free oder destroy tust, dann wird die Variable Files nicht nil gesetzt. Leider hilft hier meiner Erfahrung nach auch kein Assigned. Dort wird auch nur geprüft, ob nil.

Ich habe mir folfendes angewöhnt:
Delphi-Quellcode:
  try
    IF assigned(Files) then FreeandNil(Files);
  finally
    Files := nil;
  end;
Ich finde diese Variante auch nicht besonders toll, aber es funzt.

Gruß oki

(oki edit: except in finally)

Muetze1 7. Sep 2006 08:58

Re: Probleme mit TStrings/TStringlist beim Freigeben
 
1. Die IF Abfrage kannst du dir sparen, weil das macht Free selber auch...
2. FreeAndNil() kannst du dir auch sparen und einfach nur Free aufrufen, da der Finally Block ja so oder so aufgerufen wird...

oki 7. Sep 2006 11:21

Re: Probleme mit TStrings/TStringlist beim Freigeben
 
Hi Muetze1,

Du hast recht wenn alles so geht wie soll. Meine Erfahrungen sind aber folgende:

- Free setzt Variable nicht auf nil,
- If Assigned() liefert nach Free True,

Nun probier mal folgendes aus:
Delphi-Quellcode:
procedure TForm1.SpeedButton1Click(Sender: TObject);
var O : TObject;
begin
  O.free;
end;
Und die Exception läßt grüßen. :zwinker:

gruß oki

oki 7. Sep 2006 11:28

Re: Probleme mit TStrings/TStringlist beim Freigeben
 
Hi Muetze1,

tschuldige, habe folgenden Kommentar weiter oben von dir übersehen:
Zitat:

Zitat von Muetze1
Zitat:

Zitat von 3_of_8
Free funktioniert auch bei nicht instantiierten Objekten. Der Grund liegt auf der Hand.

Man sollte dazu aber erwähnen, dass Free nur dann ordentlich mit nicht-instanziierten Objekten funktioniert, wenn entweder eine gültige Instanzenadresse in der Variablen enthalten ist oder Nil. Bei allem anderen knallt es auch mit Free - ausser man hat ein wenig Glück und der Sprung in's Datennirvana beim Aufruf vom Destruktor landet irgendwo bei was kompatiblen...

Nun sollte man wirklich finally gegen except oder FreeandNil gegen Free austauschen.

gruß oki

xZise 7. Sep 2006 16:19

Re: Probleme mit TStrings/TStringlist beim Freigeben
 
Hier ist die Unit:

Delphi-Quellcode:
type
  TfrmOp = class(TForm)
    {...}
  private
    {...}
    Files : TStrings;
    {...}
  public
    {...}
  end;

var
  frmOp    : TfrmOp;
  {...}

implementation

{$R *.dfm}

{...}

function TfrmOp.Execute : Boolean;
var i : Integer;
begin
  {...}

  try
    // Show form
    ShowModal;
    if Files <> nil then
      Files.Free;
    Files := TStringList.Create;

    // Return Files
    if not Abort then begin
      for i := FoundDirs.Count - 1 to DataView.Items.Count - 1 do begin
        if DataView.Items[i].Selected then
          Files.Add(FolderShellTreeView.Path + '\' + DataView.Items[i].Caption);
      end;
    end;
  finally
    {...}
  end;
end;

function TfrmOp.GetFiles : TStrings;
begin
  if Files <> nil then
    Result := Files;
end;

procedure TfrmOp.FolderShellTreeViewChange(Sender: TObject;
  Node: TTreeNode);
var
  sr : TSearchRec;
  Ext : string;
begin
  DataView.Clear;
  if (FoundFiles <> nil) and (FoundDirs <> nil) then begin
    FoundFiles.Clear;
    FoundDirs.Clear;
    if FindFirst(FolderShellTreeView.Path + '\*.*',faAnyFile,sr) = 0 then
      try
        repeat
          if ((sr.Attr and faDirectory) = faDirectory) then begin
            if not((sr.Name = '.') or (sr.Name = '..')) then begin
              Application.ProcessMessages;
              with DataView.Items.Add do begin
                ImageIndex := 0;
                Caption := sr.Name;
              end;
              FoundDirs.Add(sr.Name);
            end;
          end;
        until FindNext(sr) <> 0;
      finally
        FindClose(sr);
      end;
    if FindFirst(FolderShellTreeView.Path + '\*.*',faAnyFile,sr) = 0 then
      try
        repeat
          if ((sr.Attr and faDirectory) <> faDirectory) then begin
            Application.ProcessMessages;
            Ext := LowerCase(ExtractFileExt(sr.Name));
           // if (Ext = '.mp3') or (Ext = '.wav') then begin
           //   with DataView.Items.Add do begin
           //     ImageIndex := 1;
           //     Caption := sr.Name;
           //   end;
           //   FoundFiles.Add(sr.Name);
           // end;

            if cbFilter.ItemIndex = 0 then
            begin
              if (Ext = '.mp3') or (Ext = '.wav') or (Ext = '.wma')
                or (Ext = '.aiff') or (Ext = '.ogg') or (Ext = '.mpeg')
                or (Ext = '.mpg') or (Ext = '.wmv') or (Ext = '.avi') then
              begin
                with DataView.Items.Add do
                begin
                  ImageIndex := 1;
                  Caption := sr.Name;
                end;
                FoundFiles.Add(sr.Name);
              end;
            end else

            if cbFilter.ItemIndex = 1 then
            begin
              if (Ext = '.mp3') or (Ext = '.wav') or (Ext = '.wma')
                or (Ext = '.aiff') or (Ext = '.ogg') then
              begin
                with DataView.Items.Add do
                begin
                  ImageIndex := 1;
                  Caption := sr.Name;
                end;
                FoundFiles.Add(sr.Name);
              end;
            end else

            if cbFilter.ItemIndex = 2 then
            begin
              if (Ext = '.mpeg') or (Ext = '.mpg') or (Ext = '.wmv')
                or (Ext = '.avi') then
              begin
                with DataView.Items.Add do
                begin
                  ImageIndex := 1;
                  Caption := sr.Name;
                end;
                FoundFiles.Add(sr.Name);
              end;
            end else

            if cbFilter.ItemIndex = 3 then
            begin
              if (Ext = '.mp3') then
              begin
                with DataView.Items.Add do
                begin
                  ImageIndex := 1;
                  Caption := sr.Name;
                end;
                FoundFiles.Add(sr.Name);
              end;
            end else

            if cbFilter.ItemIndex = 4 then
            begin
              if (Ext = '.wav') then
              begin
                with DataView.Items.Add do
                begin
                  ImageIndex := 1;
                  Caption := sr.Name;
                end;
                FoundFiles.Add(sr.Name);
              end;
            end else

            if cbFilter.ItemIndex = 5 then
            begin
              if (Ext = '.ogg') then
              begin
                with DataView.Items.Add do
                begin
                  ImageIndex := 1;
                  Caption := sr.Name;
                end;
                FoundFiles.Add(sr.Name);
              end;
            end else

            if cbFilter.ItemIndex = 6 then
            begin
              if (Ext = '.wma') then
              begin
                with DataView.Items.Add do
                begin
                  ImageIndex := 1;
                  Caption := sr.Name;
                end;
                FoundFiles.Add(sr.Name);
              end;
            end else

            if cbFilter.ItemIndex = 7 then
            begin
              if (Ext = '.aiff') then
              begin
                with DataView.Items.Add do
                begin
                  ImageIndex := 1;
                  Caption := sr.Name;
                end;
                FoundFiles.Add(sr.Name);
              end;
            end else

            if cbFilter.ItemIndex = 8 then
            begin
              if (Ext = '.mpeg') or (Ext = '.mpg') then
              begin
                with DataView.Items.Add do
                begin
                  ImageIndex := 1;
                  Caption := sr.Name;
                end;
                FoundFiles.Add(sr.Name);
              end;
            end else

            if cbFilter.ItemIndex = 9 then
            begin
              if (Ext = '.wmv') then
              begin
                with DataView.Items.Add do
                begin
                  ImageIndex := 1;
                  Caption := sr.Name;
                end;
                FoundFiles.Add(sr.Name);
              end;
            end else

            if cbFilter.ItemIndex = 10 then
            begin
              if (Ext = '.avi') then
              begin
                with DataView.Items.Add do
                begin
                  ImageIndex := 1;
                  Caption := sr.Name;
                end;
                FoundFiles.Add(sr.Name);
              end;
            end else

            if cbFilter.ItemIndex = 11 then
            begin
              if (Ext = '.mp3') or (Ext = '.wav') or (Ext = '.wma') or (Ext = '.aiff') or (Ext = '.ogg') then begin
                with DataView.Items.Add do begin
                  ImageIndex := 1;
                  Caption := sr.Name;
                end;
              end else if (Ext = '.mpeg') or (Ext = '.mpg') or (Ext = '.wmv') or (Ext = '.avi') then begin
                with DataView.Items.Add do begin
                  ImageIndex := 2;
                  Caption := sr.Name;
                end;
              end else begin
                with DataView.Items.Add do begin
                  ImageIndex := 3;
                  Caption := sr.Name;
                end;
              end;
              FoundFiles.Add(sr.Name);
            end;
          end;
        until FindNext(sr) <> 0;
      finally
        FindClose(sr);
      end;
  end;
end;

procedure TfrmOp.DataViewDblClick(Sender: TObject);
var
  i : Integer;
  Path : string;
begin
  if DataView.Selected <> nil then begin
    for i := 0 to DataView.Items.Count do begin
      if DataView.Items[i].Selected then begin
        // Is Directory
        if i < FoundDirs.Count then begin
          Path := FolderShellTreeView.Path;
          if FolderShellTreeView.Path[Length(FolderShellTreeView.Path)] <> '\' then
            Path := Path + '\';
          FolderShellTreeView.Path := Path + FoundDirs[i];
        end;
      end;
    end;
  end;
end;

procedure TfrmOp.DataViewSelectItem(Sender: TObject; Item: TListItem;
  Selected: Boolean);
var
  i : Integer;
  Path : string;
begin
  xiOpen.Enabled := false;
  if DataView.Selected <> nil then begin
    for i := 0 to DataView.Items.Count do begin
      if DataView.Items[i].Selected then begin
        xiOpen.Enabled := true;
      end;
    end;
  end;
end;

end.

Bernhard Geyer 7. Sep 2006 16:49

Re: Probleme mit TStrings/TStringlist beim Freigeben
 
Setzte die Zeile:

Delphi-Quellcode:
    Files := TStringList.Create;
ins OnCreate-Event und an die entsprechende Stelle
Delphi-Quellcode:
Files.Clear;
Delphi-Quellcode:
TfrmOp.GetFiles
ist auch sehr unglücklich wenn Files = nil. Dann ist der Rückgabewert undefiniert (solltest eine Compilerwarning bekommen).

xZise 7. Sep 2006 16:56

Re: Probleme mit TStrings/TStringlist beim Freigeben
 
Okay... So funktionierts NICHT!

[edit]Doch nicht ![/edit]

Nils_13 9. Sep 2006 15:23

Re: Probleme mit TStrings/TStringlist beim Freigeben
 
Liste der Anhänge anzeigen (Anzahl: 1)
Der NICHT funktionierende Code:

xZise 13. Sep 2006 20:33

Re: Probleme mit TStrings/TStringlist beim Freigeben
 
Hallo? Niemand eine Idee? Find ich geil :D Wir haben einen Delphi-Bug (gefunden)...


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:23 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 by Thomas Breitkreuz