Speicherleck
-
Lecker schrieb:
Ich verwende "crt dump memory leaks" und versuche Speicherlecks zu finden.
Es meldet bei diesem Programm welche:Meldet es auch, an welcher Stelle der Speicher geholt wurde? Gut möglich, dass da noch globale Objekte von den Bilbiotheken rumhängen, die erst nach dem Verlassen von main() gelöscht werden. Ein Profiler wird dir etwas mehr sagen können.
-
Tatsächlich benutzt SFML einige globale Objekte (z.B. OpenGL-Context), welche erst nach dem Prüfen nach Memory Leaks zerstört werden.
Übrigens würde ich eher
std::runtime_errorstattstd::logic_errorverwenden, ausserdem empfehle ich Slashes statt Backslashes in Include-Pfaden.
-
Hier noch ein Memory Leak Detector für Visual Studio:
http://vld.codeplex.com/Ev. kommen da andere Resultate dabei raus.
-
Lecker schrieb:
#include "ImageManager.h" ImageManager::ImageManager(std::string rel_path) //const std::string & { boost::filesystem::path path(boost::filesystem::initial_path().string() + rel_path); //path hat einen operator / für so etwas, der das korrekt macht boost::filesystem::directory_iterator end; if ( boost::filesystem::is_directory(path) ) { int size = 0; //size_t meinst du wohl for (boost::filesystem::directory_iterator iter(path); iter != end; ++iter) ++size; images.reserve(size); //wozu? Das zusätzliche Iterieren über das Verzeichnis dauert vermutlich viel länger als das Reallozieren std::size_t i = 0; //ist das nötig? for (boost::filesystem::directory_iterator iter(path); iter != end; ++iter, ++i) { sf::Image temp; sf::Sprite sprite; if (temp.LoadFromFile(iter->path().string())) //Fehlerbehandlung? { images.push_back(temp); sprite.SetImage(images[i]); //meinst du vielleicht images.back() ? sprites[iter->path().stem().string()] = sprite; } } } else { throw(std::logic_error("File not found")); //welche Datei? } } sf::Sprite ImageManager::get_sprite(std::string name) //const std::string & { if (sprites.count(name)) return sprites[name]; else throw(std::logic_error("IMG not found")); }
-
theta schrieb:
Hier noch ein Memory Leak Detector für Visual Studio:
http://vld.codeplex.com/Ev. kommen da andere Resultate dabei raus.
Danke für den Tipp.
@Tyroxx
Danke für die Tipps, diese Designfehler hab ich übersehen.
Das mit dem reserve ist deswegen da, weil
ein sf::Sprite eine Referenz auf ein sf::Image
hat und bei Reallokation werden Referenzen
kapputt.Ich hab mir schon überlegt std::list
oder boost::shared_array zu nehmen.
-
Lecker schrieb:
@Tyroxx
Danke für die Tipps, diese Designfehler hab ich übersehen.
Das mit dem reserve ist deswegen da, weil
ein sf::Sprite eine Referenz auf ein sf::Image
hat und bei Reallokation werden Referenzen
kapputt.sf::Spriteverwendest du falsch. Das erstellt man, wenn es benötigt wird und dann auch gerne mehrmals pro Bild.
Außerdem: Wer sagt denn, dass der Iterator beide Male die gleichen Dateien auflistet? Die Anzahl kann sich doch jederzeit ändern.
-
Danke, das war mir nicht bewusst.
Eine letzte Frage. Ich will diesf::Images als
const &zurückgeben:
const sf::Image & ImageManager::getImage(const std::string & name) { if (images.count(name)) return images[name]; else throw(std::runtime_error("IMG not found")); }Ist das gutes Design? Ich werd das ganze in eine andere Klasse packen und die Images werden nicht zerstört sein, bevor ich sie benutze.
PS: Der Visual Leak Detector erkennt keine Leaks.
-
Lecker schrieb:
Es meldet bei diesem Programm welche:
(...)Guckst du (Kommentar im Code):
int main() { ImageManager img("/img"); sf::RenderWindow App(sf::VideoMode(800, 600, 32), "Image Management Test"); while (App.IsOpened()) { // Process events sf::Event Event; while (App.GetEvent(Event)) { // Close window : exit if (Event.Type == sf::Event::Closed) App.Close(); } App.Clear(); App.Draw(img.get_sprite("Unbenannt")); App.Display(); } // "ImageManager img" und "sf::RenderWindow App" sind hier noch im Scope, // wenn die dynamisch Speicher anfordern (wovon auszugehen ist), // dann ist es ganz normal dass _CrtDumpMemoryLeaks() Leaks melder _CrtDumpMemoryLeaks(); }Also besser so
int main() { { ImageManager img("/img"); sf::RenderWindow App(sf::VideoMode(800, 600, 32), "Image Management Test"); while (App.IsOpened()) ... } _CrtDumpMemoryLeaks(); }
-
Nochwas...
sf::Spritemerkt sich einen Zeiger auf dassf::Image.
Die Adresse dessf::Imagedarf sich also nicht ändern.
Tut sie aber, wenn du diesf::ImageInstanzen in einemstd::vectorverwaltest, und neue Bilder hinzufügst.Wenn du die Bilder immer im Konstruktor lädst, und danach keine weiteren mehr hinzufügst, dann ist das OK.
Wenn du aber Bilder hinzufügst nachdemget_spriteaufgerufen wurde, dann kannst du da ein Problem bekommen.------------
const sf::Image & ImageManager::getImage(const std::string & name) ...Ist das gutes Design? Ich werd das ganze in eine andere Klasse packen und die Images werden nicht zerstört sein, bevor ich sie benutze.
Och da kann man vermutlich ganz unterschiedlicher Meinung sein

Ich finde es komisch.
Und zwar weilsf::Imagein dieser Anwendung nicht "Wert-Semantik" hat, sondern "Objekt-Semantik" (heisst: die Adresse dersf::ImageDinger ist relevant).
In so einem Fall würde ich eher nen Zeiger zurückgeben. Referenz finde ich da einfach komisch.
-
hustbaer schrieb:
const sf::Image & ImageManager::getImage(const std::string & name) ...Ist das gutes Design? Ich werd das ganze in eine andere Klasse packen und die Images werden nicht zerstört sein, bevor ich sie benutze.
Och da kann man vermutlich ganz unterschiedlicher Meinung sein

Ich finde es komisch.
Und zwar weilsf::Imagein dieser Anwendung nicht "Wert-Semantik" hat, sondern "Objekt-Semantik" (heisst: die Adresse dersf::ImageDinger ist relevant).
In so einem Fall würde ich eher nen Zeiger zurückgeben. Referenz finde ich da einfach komisch.Toll: Schnittstelle aufgeweicht, nur um einen seltenen Fehler zu erschweren.
Wer mit der Referenz das Objekt kopiert, bekommt dieses Kunststück auch mit einem Zeiger hin.
Und die Verwirrung, weil auf einmal manche Zeiger Null sein können und andere nicht, gibts gratis dazu.Referenz ist da völlig in Ordnung. Wenn eine Funktion eine Referenz zurückgibt, ist schon klar, dass da keine Wertsemantik vorliegt. Kann aber noch einmal dabeistehen.
Nochmal
für die Verwendung von Boost, std,constund Referenzen. Das ist selten bei Fragenden hier.
-
theta schrieb:
Hier noch ein Memory Leak Detector für Visual Studio:
http://vld.codeplex.com/Ev. kommen da andere Resultate dabei raus.
Then it can be used with any C/C++ project simply by adding the following line to your code:
#include <vld.h>Ist das egal, wo man vld.h inkludiert? Geht das auch wenn das Programm aus mehreren Projekten/DLLs besteht oder muss man in jedem Projekt vld.h inkludieren?
-
nefrage schrieb:
Ist das egal, wo man vld.h inkludiert? Geht das auch wenn das Programm aus mehreren Projekten/DLLs besteht oder muss man in jedem Projekt vld.h inkludieren?
1. Ja
2. Die Datei muss einmal pro EXE/DLL includiert werden.