Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

17.05.2017, 17:26

[C++] SDL_ttf - RAM Speicher wird überfüllt

Hallo zusammen,

Ich bin so ziemlich neu in diesem Forum und auch noch ein Neuling in C++, deshalb weiß ich nicht genau, ob ich hier richtig liege im Forum :) .

Mein Programm (mit SDL und ttf zur Textausgabe mit eingebunden) besteht darin, dass eine Person vom Himmel herabkommende Bananen (Bananas :) ) auffängt und der Score sich dann immer jeweils um 2 erhöht. Dieser wird dann oben rechts im Spiel angezeigt.
Ich habe mir viele Tutorials angesehen und habe vieles ausprobiert, um diesen Score mit ttf anzuzeigen, wodurch ich am Ende auch geschafft habe, den entsprechenden Text einzulesen und zu zeichnen. Doch es gibt folgendes Problem, was ich auch oft als Thema sah, aber für mein Programm nicht richtig hinbekommen habe:
Immer wenn der Text gezeichnet wird, wird Speicher genommen, der nicht freigegeben wird, was dazu führt, dass der Arbeitsspeicher schnell überfüllt wird und das Programm schließlich kaum noch funktioniert (ja, dies ist ein memory leak )). Ich bin jetzt nicht der beste in SDL und weiß nicht genau, wie man explizit diesen Speicher freigibt. Hier die wichtigen Quellcodes für das Problem:


Game.hpp (Der wichtige Teil):

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Game.hpp
//

#ifndef GAME_HPP
#define GAME_HPP

#include "Player.hpp"
#include "Banana.hpp"
#include "Text.hpp"


class CGame
{
     public:
         CGame ();         
         
         void Init ();    
         void Run  ();     
         void Quit ();    

     private:
         void ProcessEvents  (); 


         bool m_bGameRun;            // Läuft das Spiel noch?
         bool m_bMenu;               // Läuft das Hauptmenü noch?
         int      m_Score;           // Der Score für ein Spiel
         CText    *m_pText;          // Text 

};

#endif


Game.cpp (Nur der wichtige Teil):

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Game.cpp
//

#include "Game.hpp"

// Konstruktor
//
// Aufgabe: Allgemmeine Initialisierungen
//
CGame::CGame()
{
    // Sprite-Instanzen auf NULL stellen
    m_pText = NULL;

} // Konstruktor



// Init
//
// Aufgabe: Initialisierung von den meisten Objekten/Variablen
//
void CGame::Init()
{
    // Klassen-Instanzen initialisieren

    m_pText = new CText;

    // Spiel und Hauptmenü laufen
    m_bGameRun = true;
    m_bMenu = true;

    // Score auf 0 setzen
    m_Score = 0;

} // Init




// Run
//
// Aufgabe: Der eigentliche "Herzschlag" des Spiels
//
void CGame::Run()
{
    
    char TextBuffer_Score[15];

    // Die "Herzschlag"-Schleife
    while (m_bGameRun == true)
    {

        // Hauptmenü aufrufen, falls noch aktiv
        if (m_bMenu == true)
        {
            Menu ();
        } // Menu

        
        // Framework updaten und Buffer löschen
        g_pFramework->Update ();
        g_pFramework->Clear  ();

        // Events überprüfen
                ProcessEvents ();

        sprintf_s(TextBuffer_Score, "Score: %i", m_Score);
        m_pText->Initialise(g_pFramework->GetRenderer(), "Schriftarten/comic.ttf", 50, TextBuffer_Score, { 0, 0, 0, 0 });
        

        // Erreichten Score anzeigen
        m_pText->display (1320, 15, g_pFramework->GetRenderer());


        // Falls 'H' gedrückt wird, zum Hauptmenü
        // zurückkehren und Spielerstand zurücksetzen
        if (g_pFramework->KeyDown(SDL_SCANCODE_H))
            m_bMenu = true;


        // Spiel darstellen
        g_pFramework->Render ();

    }

} // Run



// Quit
//
// Aufgabe: Instanzen sauber freigeben
//
void CGame::Quit()
{
    // Instanzen werden sauber freigegeben
    if (m_pText != NULL)
    {
        delete m_pText;
        m_pText = NULL;
    }

} // Quit



Text.hpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Text.hpp
//

#ifndef TEXT_HPP
#define TEXT_HPP
#include <SDL_ttf.h>
#include <SDL.h>
#include <string>
#include "Framework.hpp"

class CText
{
public:
    CText ();
    void Initialise(SDL_Renderer *renderer,
                    const string &font_path,
                    int font_size,
                    const string &message_text,
                    const SDL_Color &color);
     
    void display (int x, int y, SDL_Renderer *renderer);

    static SDL_Texture *loadFont (SDL_Renderer *renderer, const string &font_path, int font_size, const string &message_text, const SDL_Color &color);

private:
    SDL_Texture *m_text_texture = nullptr;
    mutable SDL_Rect m_text_rect;

};

#endif



Und zuletzt noch Text.cpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// Text.cpp
//

#include "Text.hpp"

CText::CText ()
{
}


void CText::Initialise(SDL_Renderer *renderer,
                      const string &font_path,
                      int font_size,
                      const string &message_text,
                      const SDL_Color &color)
{
    m_text_texture = loadFont(renderer, font_path, font_size, message_text, color);
    SDL_QueryTexture(m_text_texture, nullptr, nullptr, &m_text_rect.w, &m_text_rect.h);
}


void CText::display(int x, int y, SDL_Renderer *renderer)
{
    m_text_rect.x = x;
    m_text_rect.y = y;
    SDL_RenderCopy (renderer, m_text_texture, nullptr, &m_text_rect);
    SDL_DestroyTexture(m_text_texture);


}


SDL_Texture *CText::loadFont(SDL_Renderer *renderer,
                             const string &font_path,
                             int font_size,
                             const string &message_text,
                             const SDL_Color &color)
{
    TTF_Font *font = TTF_OpenFont(font_path.c_str(), font_size);

    if (!font)
    {
        cout << "failed to load font!" << endl;
    }
    auto m_text_surface = TTF_RenderText_Solid (font, message_text.c_str(), color);
    if (!m_text_surface)
    {
        cout << "failed to load surface!" << endl;
    }
    if (!message_text.c_str())
    {
        cout << "failed to load message!" << endl;
    }
    auto text_texture = SDL_CreateTextureFromSurface(renderer, m_text_surface);
    if (!text_texture)
    {
        cout << "failed to load texture!" << endl;
    }
    SDL_FreeSurface (m_text_surface);
    return text_texture;

}



Sorry, falls das viel zu viel Quellcode ist oder ein paar Fehler durch das Kürzen des Quellcodes vorhanden sind )) .

Das Problem liegt auf jeden Fall in der Funktion Run() der Game-Klasse oder in der Text-Klasse.
Ich würde mich sehr über hilfreiche Antworten freuen und bedanke mich!



Hannibal_TheHacker (Max)

Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von »Hannibal_TheHacker« (17.05.2017, 18:29)


2

17.05.2017, 17:59

Hi Max und Willkommen im Forum! ;)

Kleiner Tipp zum Einstieg: Verwende C++ Code-Tags, für besseres Syntax-Highlighting.
fka tm

3

17.05.2017, 18:05

Hi Max und Willkommen im Forum! ;)

Kleiner Tipp zum Einstieg: Verwende C++ Code-Tags, für besseres Syntax-Highlighting.



Gut, danke für den Tipp )).

Ich muss nur noch herausfinden, wie das genau geht. :D

4

17.05.2017, 18:07

Ich freue mich schon auf Antworten! :)

Falls welche kommen... :thumbsup:

5

17.05.2017, 18:15

[cpp] statt [code] (analog natürlich auch die schließenden Tags)
Da werden die Antworten nur so reinrauschen! ;)
fka tm

6

17.05.2017, 18:17

[cpp] statt [code] (analog natürlich auch die schließenden Tags)
Da werden die Antworten nur so reinrauschen! ;)

Danke sehr! :thumbup:

Tobiking

1x Rätselkönig

  • Private Nachricht senden

7

17.05.2017, 18:31

Ich sehe auf jeden Fall schon mal ein OpenFont ohne CloseFont. Dazu kommt das du den Font nicht jedes Frame neu laden solltest. Wenn die Methode schon Initialise heißt macht es doch Sinn sie einmalig initial aufzurufen ;)

8

17.05.2017, 18:41

Ich sehe auf jeden Fall schon mal ein OpenFont ohne CloseFont. Dazu kommt das du den Font nicht jedes Frame neu laden solltest. Wenn die Methode schon Initialise heißt macht es doch Sinn sie einmalig initial aufzurufen ;)

Danke für die Antwort!

Aber wie soll das denn ungefähr aussehen?

9

17.05.2017, 19:26

Wo soll CloseFont denn stehen?

In Initialise?
Aber muss ich dafür dann eine neue Membervariable mit TTF_FONT ertsellen und font dort speichern?

10

17.05.2017, 19:58

Also ich kenne mich zwar nicht mit SDL und ttf aus, aber ich hätte das CloseFont in deine Quit Funktion gegeben (bzw. dort eine Funktion wie z.B.: CText::Exit, in der CloseFont aufgerufen wird, aufgerufen).
Albert Einstein sagte: "2 Stunden mit einem netten Mädchen fühlen sich an wie 20 Minuten, 20 Minuten auf einem heißen Ofen fühlen sich an wie 2 Stunden. - Das ist Relativität"

Werbeanzeige