AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Memleak, vermutlich bei VarArray/PSafeArray Nutzung
Thema durchsuchen
Ansicht
Themen-Optionen

Memleak, vermutlich bei VarArray/PSafeArray Nutzung

Offene Frage von "DarKlajid"
Ein Thema von DarKlajid · begonnen am 13. Mär 2006 · letzter Beitrag vom 13. Mär 2006
Antwort Antwort
DarKlajid

Registriert seit: 14. Jul 2004
5 Beiträge
 
Delphi 7 Professional
 
#1

Memleak, vermutlich bei VarArray/PSafeArray Nutzung

  Alt 13. Mär 2006, 11:48
Mahlzeit.

Bitte nicht schlagen: Ich bin eigentlich ein Jünger der GC Sprachen (.Net/Java Background) und falle hier gerade gehörig auf die Nase. Problem:

Ein Programm nutzt COM als Interface zu .Net Services und braucht dafür u.a. PSafeArrays. Die bisher simpelste Methode ein solches zu bauen schien mir ein VariantArray zu casten. D.h. ich habe eine Funktion die wie folgt aussieht:

Delphi-Quellcode:
procedure TMyType.CopyForms(var p_Param1 : IMyComType; var p_Param2 : IMyComType2; var p_Param3 : TStringList);
var
  vFormNames : Variant;
  iNameIndex : integer;
begin
  vFormNames := VarArrayCreate([0, p_Param3.Count - 1], varOleStr);

  try // try-finally
    for iNameIndex := 0 to p_Param3.Count - 1 do
    begin
      vFormNames[iNameIndex] := p_Param3[iNameIndex];
    end;

    p_Param1.CopyForms(p_Param2, PSafeArray(TVarData(vFormNames).VArray), False);
  finally
    Finalize(vFormNames);
    vFormNames := Unassigned;
  end;
end;
Abgesehen davon, dass der Code sicherlich weit davon entfernt ist, optimiert zu sein (Eine Liste durchlaufen um ein Array zu füllen? Sieht seltsam aus..):
MemProof sagt, dass in der Zuweisung eines Strings zum VarArray (in der for-loop) bei jedem Aufruf ein String leaked.. Zumindest lese ich das aus der Ausgabe - auch dort ist meine Erfahrung eingeschränkt.
Nachdem ich aber schon eine ganze Weile rumstocher und bisher trotz Google oder der Forensuche hier nichts erfahren hab: Mag mich jemand auf meinen Fehler hinweisen? Jede Hilfe wäre wirklich klasse..

Danke,
Ben
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#2

Re: Memleak, vermutlich bei VarArray/PSafeArray Nutzung

  Alt 13. Mär 2006, 13:28
Delphi-Quellcode:
// falsch:
// Interface-Zeiger werden als var-Parameter übergeben
procedure TMyType.CopyForms(var p_Param1 : IMyComType; var p_Param2 : IMyComType2; var p_Param3 : TStringList);

// richtig:
// Interface-Zeiger werden by Value übergeben
// auch Delphi-Objekte werden by Value übergeben
procedure TMyType.CopyForms(p_Param1 : IMyComType; p_Param2 : IMyComType2; p_Param3 : TStringList);
Andreas
  Mit Zitat antworten Zitat
DarKlajid

Registriert seit: 14. Jul 2004
5 Beiträge
 
Delphi 7 Professional
 
#3

Re: Memleak, vermutlich bei VarArray/PSafeArray Nutzung

  Alt 13. Mär 2006, 14:04
Zitat von shmia:
Delphi-Quellcode:
// falsch:
// Interface-Zeiger werden als var-Parameter übergeben
procedure TMyType.CopyForms(var p_Param1 : IMyComType; var p_Param2 : IMyComType2; var p_Param3 : TStringList);

// richtig:
// Interface-Zeiger werden by Value übergeben
// auch Delphi-Objekte werden by Value übergeben
procedure TMyType.CopyForms(p_Param1 : IMyComType; p_Param2 : IMyComType2; p_Param3 : TStringList);
Danke für die (knappe?) Antwort. Leider ändert das nichts an meinem Verhalten/Problem.
Will sagen:

- Funktioniert wie gehabt
- Leakt wie gehabt (laut MemProof halt genau in dieser Funktion und zwar eine Unmenge an Strings..)

Ich hab die Funktion "komprimiert" in:

Delphi-Quellcode:
procedure TMyType.CopyForms(p_Param1 : IMyComType; p_Param2 : IMyComType2; p_Param3 : TStringList);
var
  vFormNames : Variant;
begin
  try // try-finally
    vFormNames := VarArrayFromStrings(p_Param3);

    p_Param1.CopyForms(p_Param2, PSafeArray(TVarData(vFormNames).VArray), False);
  finally
    Finalize(vFormNames);
    vFormNames := Unassigned;
  end;
end;
Vorher war es die Zeile:
FormNames[iNameIndex] := p_Param3[iNameIndex]; Jetzt ist es:
vFormNames := VarArrayFromStrings(p_Param3); Der Stacktrace des Leaks ist über diesen Zeilen:
Zitat:
system.pas - WStrFromPWCharLen
variants.pas - VarFromWStr
meineUnit - DieZeileVonOben
Danke im voraus für jede Hilfe,
Ben
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#4

Re: Memleak, vermutlich bei VarArray/PSafeArray Nutzung

  Alt 13. Mär 2006, 14:28
Dann musst du den Fehler Schritt für Schritt einkreisen.
Ich würde nur mal VarArrayFromStrings für sich alleine testen.
die Funktion sieht bei dir wohl auch so aus:
Delphi-Quellcode:
function VarArrayFromStrings(list:TStrings): Variant;
var
  iNameIndex : integer;
begin
  Result := VarArrayCreate([0, list.Count - 1], varOleStr);

  for iNameIndex := 0 to list.Count - 1 do
  begin
    Result[iNameIndex] := list[iNameIndex];
  end;
end;
Ich habe diese Funktion mit MemCheck 2.73 und FastMM4 überprüft -> kein Leak.
Versuch's mal mit MemProof, könnte ja auch ein Problem von MemProof sein.
Andreas
  Mit Zitat antworten Zitat
DarKlajid

Registriert seit: 14. Jul 2004
5 Beiträge
 
Delphi 7 Professional
 
#5

Re: Memleak, vermutlich bei VarArray/PSafeArray Nutzung

  Alt 13. Mär 2006, 16:18
Ich habe gerade mit MemCheck nach eben diesem Leak gesucht und erhalte folgende Ausgabe am Ende des Programms:

MemCheck version 2.73

Total leak: 0 bytes


*** MEMCHK: Blocks STILL allocated ***

*** MEMCHK: End of allocated blocks ***


*** MEMCHK: Chronological leak information ***


*** MEMCHK: End of chronological leak information ***


*** MEMCHK: Blocks written to after destruction ***

Bad blocks count: 0


*** MEMCHK: End of blocks written to after destruction ***

Nun ja.. Schön wär's ja.. FastMM will bei mir gar keine Ausgabe machen, auch im FullDebugMode nicht.. Da ist wohl noch etwas basteln angesagt. Leider ist die Dokumentation ja recht dürftig..
  Mit Zitat antworten Zitat
DarKlajid

Registriert seit: 14. Jul 2004
5 Beiträge
 
Delphi 7 Professional
 
#6

Re: Memleak, vermutlich bei VarArray/PSafeArray Nutzung

  Alt 13. Mär 2006, 18:34
Sorry, ich will das Thema nicht pushen. Vielleicht hat aber jemand ein paar Ratschläge zu den Resultaten bisher..

Mit der memcheck Unit bekomme ich am Ende das Resultat "kein Leak gefunden". Meine Applikation startet mit 80 MB Speicherverbrauch (Overhead der externen Dependencies, nicht meine Schuld) und hat nach etwas Arbeit locker 400-500 MB im Taskmanager für sich veranschlagt. Die Daten bekomme ich schubweise und nach jeder Bearbeitung (bestehend aus einigen COM-Aufrufen hauptsächlich) ist der Speicherverbrauch signifikant höher.
FastMM bekomme ich nicht dazu, mir Hinweise/Logs in irgendeiner Art zu generieren. Ich erhalte keine Fehler mit FastMM als erster Unit, aber Leaks oder irgendwas als Report gibt es halt nicht. Die Include-Datei ist jedoch imo korrekt angepasst.
MemProof meldet mir Leaks, allerdings "nur" SysStrings. Ich denke nicht, dass ich mit Dutzenden/Hunderten von Strings (Länge entweder exakt 6 Zeichen oder grob 20, das Problem mit den VarArrays tritt an zwei Stellen auf) auf Dutzende/Hunderte von MBs an Speicherverbrauch komme? Der Stack zu den Leaks ist wie o.a. vor meiner Funktion:

System.pas:WStrFromPWCharLen
Variants.pas:VarFromWStr
... mein Kram ...

Wenn ich mir den Inhalt der Strings/Leaks anschaue, dann erkenne ich Daten, die ich als PSafeArray an COM übergeben musste. Dafür habe ich VarArrayCreate() oder VarArrayFromStrings() verwendet und das Ergebnis in ein PSafeArray gecastet. Ich will nun keineswegs Fehler auf meiner Seite oder sogar auf der COM-Seite (ein .Net Framework) ausschliessen. Ich werde sicherlich etwas sehr dummes machen - nur bin ich langsam am Ende mit Ideen.
Inzwischen falle ich schon zu einem try/finally/FreeAndNil oder Finalize um fast jedes Statement zurück.

Gibt es bekannte dumme Dinge die bei Varianten/VarArrays/PSafeArrays passieren können?

Danke für jeden Hinweis,
Ben
  Mit Zitat antworten Zitat
Neuromancer

Registriert seit: 8. Aug 2003
62 Beiträge
 
Delphi 7 Enterprise
 
#7

Re: Memleak, vermutlich bei VarArray/PSafeArray Nutzung

  Alt 13. Mär 2006, 20:38
Hallo DarKlajid,

versuche mal, das PSafeArray mit "SafeArrayDestroy" nach Gebrauch zu zerstören. Zu finden in der Unit ActiveX.

Bitte frag mich nicht, warum man ein COM-Array zerstören/freigeben muss. COM sollte sich doch eigentlich aufgrund seiner Garbage Collection selbst im Zaum halten.

Siehe dazu auch diesen Thread.

Gruß
  Mit Zitat antworten Zitat
Antwort Antwort


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 00:14 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