[Gelöst] Speicherleiche bei Texturenerzeugung mit SDL und OpenGL
-
Danke, das hat das Problem verkleinert, ist jedoch leider noch nicht beseitigt.
Der genutzte Bereich im Arbeitsspeicher steigt immer noch bei jedem Funktionsaufruf im etwa einen MiB an. Das geladene Bild ist übrigens 506,9 KB groß, falls das hilft.
Mit freundlichen Grüßen,
Ki
-
Überprüfe noch, ob eine der Funktionen, welche du verwendest, einen Zeiger als Rückgabewert hat (mit OpenGL hatte ich jetzt noch nicht so viel zu schaffen). Den solltest du eventuell auch noch abfangen und beim Rücksprung löschen.
-
Ki schrieb:
Der genutzte Bereich im Arbeitsspeicher steigt immer noch bei jedem Funktionsaufruf im etwa einen MiB an.
Schonmal überlegt, dass es daran liegen könnte, dass in jedem Aufruf eine neue Textur erzeugt wird? Kommentier eben mal das glTexImage2D() aus und schau, ob das Leak immer noch da ist
-
Nach ein paar Tests via Auskommentieren scheint es so, als würde
glTexImage2D()
der Problemverursacher sein. Ist diese Auskommentiert, tritt das Problem nicht mehr auf. Jedoch kann ich in Referenzen nichts dazu finden. Einen Rückgabewert hatglTexImage2D()
nicht, da es eine Funktion vom Typvoid
ist.Hat jemand einen Einfall?
Mit freundlichen Grüßen,
KiEDIT:
dot, du hast scheinbar RechtUnd wie kann man das Problem beheben?
-
Ich versteh nicht ganz wo dein Problem liegt? Es passiert doch genau das, was du programmiert hast!? Bei jedem Aufruf dieser Funktion wird eine neue Textur erzeugt. Natürlich braucht diese Textur auch Speicher!? Die Frage die du dir stellen solltest ist: Warum ruf ich diese Funktion so oft auf und was passiert mit den erzeugten Texturen, wenn sie nichtmehr benötigt werden?
-
dot schrieb:
Ich versteh nicht ganz wo dein Problem liegt? Es passiert doch genau das, was du programmiert hast!? Bei jedem Aufruf dieser Funktion wird eine neue Textur erzeugt. Natürlich braucht diese Textur auch Speicher!? Die Frage die du dir stellen solltest ist: Warum ruf ich diese Funktion so oft auf und was passiert mit den erzeugten Texturen, wenn sie nichtmehr benötigt werden?
Ich will im Prinzip nur eine bereits erzeugte Textur aus dem Speicher bekommen, um keine Speicherleichen zu haben.
Innerhalb der Laufzeit sollen schließlich mehrere Texturen erzeugt werden, die später nicht mehr notwendig sind.
-
Wenn du eine bereits erzeugte Textur willst, dann verwend doch einfach die bereits erzeugte Textur, anstatt eine neue zu erzeugen!?
-
ich kann doch nicht alle Texturen, die irgendwann mal gebraucht werden könnten, in den Speicher laden. Dann hätte ich bei vielen Texturen einen Instant Overflow, anstatt Leichen zu stapeln.
-
Ki schrieb:
ich kann doch nicht alle Texturen, die irgendwann mal gebraucht werden könnten in den Speicher laden.
Wer sagt dass du das sollst?
Mir ist leider immer noch völlig unklar, was genau jetzt dein Problem ist. Wenn du eine Textur nichtmehr benötigst, dann gib sie eben frei. Und wenn du eine Textur benötigst, die du noch nicht geladen hast, dann lade sie. Und wenn sie aber doch schon geladen wurde, dann verwend die geladene, anstatt eine neue zu erzeugen. Wo genau scheiterts jetzt?
-
Ich scheitere am Freigeben des Speichers innerhalb der Funktion
loadTexture()
.Ich will
loadTexture()
nutzen, um in der Laufzeit einer Variable, z.B.texture
, eine Textur zuzuweisen. Die Textur soll nur im Gültigkeitsbereich dieser Variable existieren.
-
Persönlich würde ich versuchen, das zu vermeiden. Lieber am Anfang versuchen, alles direkt zu initialisieren, einzuladen und zu sortieren, als die Textur dann zu laden, wenn Sie gebraucht wird. Früher, als der Speicher noch wirklich rar war und man selbst den Soundchipspeicher verwendet hat, um alles, was man im Spiel wollte, unterzukriegen, konnte man das machen, aber heutzutage ist Speicher billig und das Leben kurz, da sollte man die CPU/GPU nicht in der Laufzeit mit dem Laden einer eventuell aufwendigen Textur belasten - stört nur den Spielfluss.
Meine unnötige Meinung zu dem Thema.
Dann kann innerhalb des Programms mit der Tabelle gearbeitet werden, und es muss nicht ständig auf die Festplatte zugegriffen werden.
-
Der aus dem Westen ... schrieb:
Persönlich würde ich versuchen, das zu vermeiden. Lieber am Anfang versuchen, alles direkt zu initialisieren, einzuladen und zu sortieren, als die Textur dann zu laden, wenn Sie gebraucht wird. Früher, als der Speicher noch wirklich rar war und man selbst den Soundchipspeicher verwendet hat, um alles, was man im Spiel wollte, unterzukriegen, konnte man das machen, aber heutzutage ist Speicher billig und das Leben kurz, da sollte man die CPU/GPU nicht in der Laufzeit mit dem Laden einer eventuell aufwendigen Textur belasten - stört nur den Spielfluss.
Mein Programm ist modular in Szenen aufgebaut. Jede Szene ist ein Objekt einer speziellen Tochterklasse einer gemeinsamen Elternklasse. Zu Beginn jeder Szene, also beim Anlegen des Objektes, werden daher die Texturen eingeladen.
-
Was hält dich davon ab, Verweise auf die geladenen Texturen zu erstellen? Eingeladen werden müssen die so oder so, aber wenn du die Texturen in einer internen Tabelle mit Schlüsseln verpackst, sparst du einiges an Laufzeit. Wenn die Szene dann aufgerufen wird, weißt du bloß die entsprechenden und bereits geladenen Texturen zu, und fertig. Würde ich zumindest so machen . so ersparst du dir ständige Zugriffe auf die Festplatte.
-
@TE
Du solltest dich mal mit den Grundlagen beschäftigen. loadImage() gibt ein GLUint zurück - keinen Pointer. Darauf delete? Schlechte Idee. glTexImage2D kopiert das Bild übrigens, da wird Speicher reserviert! Lies die Doku! Wie wäre es, glDeleteTexture aufzurufen?
Ich will loadTexture() nutzen, um in der Laufzeit einer Variable, z.B. texture, eine Textur zuzuweisen. Die Textur soll nur im Gültigkeitsbereich dieser Variable existieren.
Was gibt es besseres als eine Klasse? Im Konstruktor erstellst du die Texture, im Destruktor gibst du sie wieder frei. Einfacher geht es wirklich nicht. Dazu noch nen Move-Konstruktor und alles ist in Butter.
-
cooky451 schrieb:
@TE
Du solltest dich mal mit den Grundlagen beschäftigen. loadImage() gibt ein GLUint zurück - keinen Pointer. Darauf delete? Schlechte Idee. glTexImage2D kopiert das Bild übrigens, da wird Speicher reserviert! Lies die Doku! Wie wäre es, glDeleteTexture aufzurufen?
Wird wo gemacht?
cooky451 schrieb:
Was gibt es besseres als eine Klasse? Im Konstruktor erstellst du die Texture, im Destruktor gibst du sie wieder frei. Einfacher geht es wirklich nicht. Dazu noch nen Move-Konstruktor und alles ist in Butter.
Die Freigabe ist das, wonach ich in diesem Thread frage. Wie gibt man den Speicherbereich der Textur effektiv frei?
EDIT:
cooky451 schrieb:
glTexImage2D kopiert das Bild übrigens, da wird Speicher reserviert! Lies die Doku! Wie wäre es, glDeleteTexture aufzurufen?
glDeleteTexture war das, wonach ich brauchte, danke
-
Ki schrieb:
Wird wo gemacht?
Hast du gerade wegeditiert,nice. Der Code ist aber immer noch ziemlich hässlich.
Ki schrieb:
GLuint *image = new GLuint; *image = loadTexture("img.png"); delete image;
Oh man.. bist du Java programmierer?
Ich habe dir doch schon geschrieben, wie du du das freigibst. Lies die Beiträge hier. glDeleteTexture. [Edit: Na das hast du gefunden, immerhin. :p ]
Mal ein Beiespiel:
class Texture { GLUint id_; public: Texture(const std::string &filename) { // Hier Textur laden. Als "object" id_ nutzen. } Texture(Texture &&texture) : id_(texture.id_) // Move Konstruktor. { texture.id_ = 0; } ~Texture() { glDeleteTextures(1, &id_); // Hier wird die Textur freigegeben. } };
Anwendung:
void foo() { Texture texture("xyz.zyx"); // Hier wird die Textur geladen } // Destruktor gibt frei.
-
cooky451 schrieb:
Ki schrieb:
Wird wo gemacht?
Hast du gerade wegeditiert,nice. Der Code ist aber immer noch ziemlich hässlich.
Ich habe nur den Datentyp geändert, bei dem ich mich vertippt habe.
cooky451 schrieb:
Ki schrieb:
GLuint *image = new GLuint; *image = loadTexture("img.png"); delete image;
Oh man.. bist du Java programmierer?
Es liegt mir fern, Trolle zu unterstützen, aber du solltest vielleicht mal darüber nachdenkt, ob man schnelle Code-Beispiele nicht eventuell immer auf das notwendigste reduziert.
cooky451 schrieb:
Ich habe dir doch schon geschrieben, wie du du das freigibst. Lies die Beiträge hier. glDeleteTexture.
Las ich erst nach dem Posten, daher mein EDIT.
Klassen anlegen kann ich selbst, dennoch danke.
-
Ki schrieb:
Ich habe nur den Datentyp geändert, bei dem ich mich vertippt habe.
Ja.. und ein paar Sternchen gemacht, die die Bedeutung deines Codes völlig verändert haben.
Ki schrieb:
Es liegt mir fern, Trolle zu unterstützen, aber du solltest vielleicht mal darüber nachdenkt, ob man schnelle Code-Beispiele nicht eventuell immer auf das notwendigste reduziert.
Du schreibst also ernsthaft:
void foo() { int *i = new int; *i = 5; delete i; }
statt
void foo() { int i = 5; }
? Super.
Ki schrieb:
Klassen anlegen kann ich selbst, dennoch danke.
Ja, das sehe ich.
-
Auch wenn es amüsant ist, zu sehen, wie deine Arroganz deine Fähigkeit, Sachverhalte und den beabsichtigten Sinn dahinter korrekt zu reflektieren, trübt:
CLOSED
Deal with it.
Auf weiteren Streit werde ich nur via Mail eingehen.
-
Ki schrieb:
Auch wenn es amüsant ist, zu sehen, wie deine Arroganz deine Fähigkeit, Sachverhalte und den beabsichtigten Sinn dahinter korrekt zu reflektieren, trübt:
Ich würde mir seine Anmerkungen an deiner Stelle zu Herzen nehmen. Er hat dich auf ein Problem mit deinem Code hingewiesen, offenbar mangelt es dir noch an wesentlichen Grundlagen, was C++ angeht. Ich kann dir nur empfehlen, zumindest mal ernsthaft drüber zu reflektieren.
Ki schrieb:
Ich will
loadTexture()
nutzen, um in der Laufzeit einer Variable, z.B.texture
, eine Textur zuzuweisen. Die Textur soll nur im Gültigkeitsbereich dieser Variable existieren.Und die Lösung dafür, hat cooky451 dir in seinem vorletzten Post geliefert. Du solltest versuchen, ihn zu verstehen.
Der aus dem Westen ... schrieb:
Persönlich würde ich versuchen, das zu vermeiden. Lieber am Anfang versuchen, alles direkt zu initialisieren, einzuladen und zu sortieren, als die Textur dann zu laden, wenn Sie gebraucht wird.
Ja, das kannst du vielleicht bei einem Pong machen. Aber bei nem richtigen Spiel wird man alles mögliche unternehmen, um gerade bei Texturen den Speicherverbrauch unter Kontrolle zu halten. 512MB sind sehr schnell mal voll.