Seite 1 von 1

memory leak

Verfasst: Sonntag 7. Oktober 2007, 18:12
von alan
Hallo

Ich habs gerade geschafft, folgenden Fehler (reproduzierbar) zu erhalten.
Kann mir jemand sagen, ob ich da schuld dran bin oder wx selbst? :?:
swig/python detected a memory leak of type 'wxPyTreeCtrl *', no destructor found.
Traceback (most recent call last):
File "wx_gui.py", line 366, in OnImport
self.panel.tree.__init__(self.panel1)
File "wx_gui.py", line 229, in __init__
wx.TreeCtrl.__init__(self, parent, -1, style=style)
File "/usr/lib/python2.5/site-packages/wx-2.8-gtk2-unicode/wx/_controls.py", line 5177, in __init__
self._setOORInfo(self);TreeCtrl._setCallbackInfo(self, self, TreeCtrl)
File "/usr/lib/python2.5/site-packages/wx-2.8-gtk2-unicode/wx/_core.py", line 3772, in _setOORInfo
args[0].this.own(False)
File "/usr/lib/python2.5/site-packages/wx-2.8-gtk2-unicode/wx/_core.py", line 13772, in __getattr__
raise PyDeadObjectError(self.attrStr % self._name)
wx._core.PyDeadObjectError: The C++ part of the CategoriesList object has been deleted, attribute access no longer allowed.

Verfasst: Montag 8. Oktober 2007, 14:27
von CM
Bin mir nicht sicher, ob dazu irgendjemand irgendetwas sagen kann, wenn Du uns nicht verrätst, wie denn dieser Fehler überhaupt provoziert wurde.

Allerdings klingt die Fehlermeldung schon etwas seltsam. Will ich wohl zugeben ...

Gruß,
Christian

Verfasst: Montag 8. Oktober 2007, 14:40
von alan
Ja ich weiß..aber ich kann nicht wirklich meinen ganzen Code posten und ich habs bis jetzt nicht geschafft, das zusammenzukürzen und den Fehler zu behalten. Ich probiers später nochmal und meld mich dann.

Verfasst: Montag 8. Oktober 2007, 14:59
von CM
Eindampfen sowieso und ggf. auch http://paste.pocoo.org/

Gruß,
Christian

Verfasst: Montag 8. Oktober 2007, 17:04
von alan
Tja, also da ist was faul.

(Auch hier ausgelagert)

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import wxversion
wxversion.ensureMinimal("2.7.1")
import wx


class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1)
        self.label = wx.StaticText(self, -1, "Hello World")
        self.CrashMe()

    def CrashMe(self):
        self.label.__init__(self, -1, "Oh no")


app = wx.PySimpleApp()
frame = MyFrame()
frame.Show()
app.MainLoop()
Ergibt den bekannten Fehler.

Interessant ist, dass das nicht nur mit wx.TreeCtrl funktioniert, sondern auch mit anderen (hier z.B. wx.StaticText).

Der Fehler tritt bei mir unter Linux/Gtk mit der 2.6er (ich hab 2.6.3.2) nicht auf, nur bei der 2.8er (2.8.1.1).

Mach ich hier was falsch oder bin ich über einen Bug gestolpert? :roll:

Verfasst: Montag 8. Oktober 2007, 17:16
von gerold
Hallo alan!

In Zeile 13 wird dein Label initialisiert. Einmal! Mehr ist nicht! -- Du kannst/darfst es nicht noch einmal initialisieren. Es gibt auch keinen Grund dafür.

Falls du in deinem Code so etwas öfter machst --> FEHLER!!! Sofort ausbessern. Dann stimmt etwas nicht.

Wenn du nur den Text ändern möchtest:

Code: Alles auswählen

self.label.SetLabel("Oh yes")
self.label.Refresh()
mfg
Gerold
:-)

Verfasst: Montag 8. Oktober 2007, 17:19
von CM
Ahaaaa!
Was möchtest Du denn eigentlich erreichen? Die __init__-Methode eines Widgets aufrufen, nachdem es längst erzeugt und plaziert wurde. Das ist generell keine gute Idee. In dem Zusammenhang ist die Fehlermeldung absolut sinnvoll.

Was willst Du denn eigentlich *wirklich* erreichen? Einen statischen Text läßt man eigentlich unangetastet. Man schließt oder ersetzt oder verändert allenfalls das Widget in dem er vorkommt (oder verändert den Text an sich ...)

Die __init__-Methode einer TreeCtrl kannst Du beispielsweise in einem Panel aufrufen:

Code: Alles auswählen

wx.TreeCtrl.__init__(self, parent, ...)
aber wenn Du das Ctrl zuweist:

Code: Alles auswählen

self.tree = MyTreeCtrl(self, ....)
kannst Du anschließend keine __init__ von self.tree aufrufen.

Gruß,
Christian

Verfasst: Montag 8. Oktober 2007, 17:20
von alan
Hmm eigentlich habe ich das bei meinem TreeCtrl gemacht, nachdem neuen Daten zum Darstellen waren. Den entsprechenden Code kann ich natürlich von __init__ in eine andere Methode schieben.

Aber wieso produziert das erst in der 2.8-Version einen Fehler?

Verfasst: Montag 8. Oktober 2007, 17:20
von BlackJack
Ich würde sagen Du machst was falsch. Das man einfach so die `__init__()` erneut aufrufen kann und danach einen definierten Zustand des Objekts hat, ist jedenfalls nicht garantiert. Selbst in reinem Python-Code nicht.

In der `__init__()` wird wahrscheinlich im C++-Teil ein "echtes" wxStaticText-Widget neu erzeugt. Und wenn Du das noch einmal aufrufst, dann wird vielleicht wieder ein neues erzeugt, ohne das alte zu zerstören.

Verfasst: Montag 8. Oktober 2007, 17:25
von CM
alan hat geschrieben:Aber wieso produziert das erst in der 2.8-Version einen Fehler?
Weil zwischenzeitlich am API rumgefummelt wurde. Das stellt aber eine Verbesserung dar, weil es Dich (uns) solche Fehler nicht mehr machen läßt.

Gruß,
Christian

Verfasst: Montag 8. Oktober 2007, 17:28
von CM
Außerdem: Der Traceback hat *nichts* mit einem Memory Leak zu tun. Wäre vielleicht gut in Zukunft Threads ein bißchen aussagekräftiger zu bennenen. ;-)

Verfasst: Montag 8. Oktober 2007, 17:36
von alan
Aha jetzt bin ich schlauer :) Danke.

Wegen dem Titel: Ich konnte mit dem Fehler nicht wirklich was anfangen und ein Google-Treffer hat irgendwas von GC+memory leak gefaselt. No pun intended :-)