Memory leak while using SDL

Hello,
I created this program to create a carousel type of display after reading from a json web file. Everything basically works okay but for some reason, it never stops using up memory. I’m sure its because its drawing SDL surfaces and textures but in my code, I destroy all the surfaces and textures I create in the main loop so I don’t know why it keeps continuing to somehow create more sdl textures and surfaces even though I seem to be explicitly destroying what I create. I tried to post my code but this forum kept saying I’m limited to two links a post, which I took out, but still wouldn’t let me post. Here is a google drive link to it.

https://drive.google.com/file/d/1Mt4OEzVfvAUJgl5GVB1IFtPtZauUJSiV/view?usp=sharing

Hi and welcome to the forum!

Please show us your main loop by pasting the relevant code into this thread. It’s easier to view it here than going to external sites and/or downloading a package of the whole project.
Don’t forget to surround the code in code tags so it gets its indentation done correctly.

I tried to paste it to here but like I said above, imy posting kept being rejected because it said I had too many links for a new user. Would you be able to get my code and post it for me? It will not allow me to post.

Oh btw. What are code tags?

You just have to copy the relevant code lines from your project, like the mainloop, where you create and destroy the surface/texture, paste it here, select all and then press the </> button in the tool box, which will indent each line of code by 4 spaces, effectively turning the code into a code block.

Example:

while(true)
{

}

while (!ended)
{ // Start counting the frame rate.
startMs = SDL_GetTicks();

    while (SDL_PollEvent(&event));
    {
        // Let the user X out of the app.
        if (event.type == SDL_QUIT)
        {
            //Quit the program
            ended = true;
        }

        switch (event.type)
        {
            case SDL_KEYDOWN:
            {
                switch (event.key.keysym.sym)
                {
                case SDLK_LEFT:
                    move_left(renderer);
                    break;
                case SDLK_RIGHT:
                    move_right(renderer);
                    break;
                default:
                    break;
                }
            }// end of switch
        }
    }

    // The background was downloaded in ParseJson so just load it here.
    SDL_Texture* backgroundTexture = LoadTexture(renderer, "background.jpg");
    SDL_RenderCopy(renderer, backgroundTexture, NULL, NULL);

    for (int x = 0; x < numItems; x++)
    {
        // this is where you blight the image on the SDL_Rectangle.
        SDL_RenderCopy(renderer, carouselCardImages[x], NULL, &cardsPositionLst[x]);
    }

    showCardHeadline(cardX, cardY);
    showCardCaption(cardX, cardY);

    // Present all of the stuff copied.
    SDL_RenderPresent(renderer);

    // Destroy everything created in this frame
    // and create them again in the next frame.
    SDL_DestroyTexture(backgroundTexture);

    endMs = SDL_GetTicks();
    delayMs = (endMs - startMs);
    //SDL_Delay(delayMs);

}//end of main render loop.

curl_global_cleanup();

}//end of main.

// Generate a headline above the picture by creating an
// sdl surface and then turning that into an sdl_texture.
void showCardHeadline(int cardX, int cardY)
{
TTF_Init();

cardX = 10;
cardY = 50;

TTF_Font* font = TTF_OpenFont("open-sans/OpenSans-Regular.ttf", 11);
if (!font) 
{
    std::cout << "Failed to load font: " << TTF_GetError() << std::endl;
}

// Set color to white
SDL_Color color = {255,255,255};

textSurface = TTF_RenderText_Solid(font, carouselCardsStructs[0].headline.c_str(), color);
if (!textSurface) 
{
    std::cout << "Failed to render textSurface: " << TTF_GetError() << std::endl;
}

textSurface->w = 300;
textSurface->h = 15;

text_texture = SDL_CreateTextureFromSurface(renderer, textSurface);

SDL_Rect dest = {cardX, cardY, textSurface->w, textSurface->h};

SDL_RenderCopy(renderer, text_texture, NULL, &dest);

SDL_DestroyTexture(text_texture);
SDL_FreeSurface(textSurface);

}

// Shows the caption at the bottom of a carousel card.
void showCardCaption(int cardX, int cardY)
{
// Initialize font.
TTF_Init();

cardX = 10;
cardY = 300;

TTF_Font* font = TTF_OpenFont("open-sans/OpenSans-Regular.ttf", 9);
if (!font)
{
    std::cout << "Failed to load font: " << TTF_GetError() << std::endl;
}

// Set color to white
SDL_Color color = {255,255,255};

SDL_Surface* textSurface = TTF_RenderText_Solid(font, carouselCardsStructs[0].caption.c_str(), color);
if (!textSurface)
{
    std::cout << "Failed to render text: " << TTF_GetError() << std::endl;
}

textSurface->w = 300;
textSurface->h = 12;

SDL_Texture* text_texture;

text_texture = SDL_CreateTextureFromSurface(renderer, textSurface);

SDL_Rect dest = { cardX, cardY, textSurface->w, textSurface->h };

SDL_RenderCopy(renderer, text_texture, NULL, &dest);

SDL_DestroyTexture(text_texture);
SDL_FreeSurface(textSurface);

}

// move all the carousel cards towards the left subtracting cards

// at end of the list of carousel cards.
bool move_right(SDL_Renderer* renderer)
{
// movement is towards the left. (+)------->(-)
rightBoundary–;
if (leftBoundary < 0)
{
leftBoundary = cardsPositionLst.size() - 1;
}

leftBoundary--;
if (rightBoundary < 0)
{
    rightBoundary = cardsPositionLst.size() - 1;
}

// Save the position being erased.
CarouselCard tempCard;
tempCard.image_filename = carouselCardsStructs.at(numItems - 1).image_filename;
tempCard.index = carouselCardsStructs.at(numItems - 1).index;
tempCard.headline = carouselCardsStructs.at(numItems - 1).headline;
tempCard.caption = carouselCardsStructs.at(numItems - 1).caption;

// Start at the end of the array and 
// copy everything on the left to the right.
for (int i = numItems - 1; i >= 1; i--)
{
    carouselCardImages.at(i) = carouselCardImages.at(i - 1);

    // Copy the rest of the card's info into the carouselCard struct.
    carouselCardsStructs.at(i).image_filename = carouselCardsStructs.at(i - 1).image_filename;
    carouselCardsStructs.at(i).index = carouselCardsStructs.at(i - 1).index;
    carouselCardsStructs.at(i).headline = carouselCardsStructs.at(i - 1).headline;
    carouselCardsStructs.at(i).caption = carouselCardsStructs.at(i - 1).caption;
}

carouselCardImages.at(0) = LoadTexture(renderer, tempCard.image_filename);

// Copy the rest of the card's info into the carouselCard struct.
carouselCardsStructs.at(0).image_filename = tempCard.image_filename;
carouselCardsStructs.at(0).index = tempCard.index;
carouselCardsStructs.at(0).headline = tempCard.headline;
carouselCardsStructs.at(0).caption = tempCard.caption;

// Destroy the heading text.
SDL_DestroyTexture(text_texture);

return false;

}// end move_right

Sorry about so many posts in a row but it only worked when I broke up the code into smaller parts. When I tried to paste the whole thing, it kept telling me that I was trying to post more than one link.

In the showCardHeadline() and showCardCaption() functions, you’re creating/loading a font with TTF_OpenFont(), each frame, without destroying it. I’m fairly sure that’s what causing the memory leak.

I understand that you need to recreate a surface and a texture while rendering text with the TTF_RenderText_Solid() function, but you should be able to load the background texture and the font(s) at the start-up of the application, instead of creating/loading those objects every frame.

The TTF_Init() function should only be executed (once) at the start-up of the application aswell.

Thank you. I’m sure that is part of the problem but I’m still leaking memory somewhere.

Okay. I fixed the last issue real quick by making my font variable global and just creating it one time when main starts. I also took out TTF_Init and put it in main one time instead of calling each each frame. Its still causing a memory leak somehow from somewhere else.
I can probably slow down the leak by using preloaded texts like I do the pictures. I’m already loading the strings into a vector when I parse the json file. I was already getting a memory leak however before I added the text headline and caption.
Another problem I’m having is that the text repeats inside of the surface that I turn into a texture. The text heading and caption is repeated inside of the SDL_Surface.

I also commented out the showCardHeadline/Caption and I’m still getting a memory link.

In the move_right() function, you have some kind of array of carouselCardImages, which are created each frame aswell but I can’t see that you actually destroy those later in the render stage.

Also: why are you destroying the text_texture both in the showCardCaption() function and the move_right() function?

The images in that vector which are in that array are not created every every press. One texture is deleted and one is created and placed onto the right or left side respectively. Each one is shifted left or right depending on the direction chosen however.

There’s a problem here:

for (int i = numItems - 1; i >= 1; i--)
{
    carouselCardImages.at(i) = carouselCardImages.at(i - 1);

    // Copy the rest of the card's info into the carouselCard struct.
    carouselCardsStructs.at(i).image_filename = carouselCardsStructs.at(i - 1).image_filename;
    carouselCardsStructs.at(i).index = carouselCardsStructs.at(i - 1).index;
    carouselCardsStructs.at(i).headline = carouselCardsStructs.at(i - 1).headline;
    carouselCardsStructs.at(i).caption = carouselCardsStructs.at(i - 1).caption;
}

Here you move every object, stored in the vector/array, to the right. What happens with the previously created texture data that carouselCardImages[i] (might) contain? Do you properly destroy that data before replacing the index with data from the precious index?
I might have missed that in your code.

That’s a good place to look. I don’t destroy the data previously there before it is moved. I will try that and let you know.

One thing is when I comment out everything in my main loop, the leak stops so its one of the loop functions causing the problems. Move left and move right dont get called every frame but the leak looks like it is called every frame because of the rate at which it grows. Even if I comment out everything but the background which I destroy at the end of the loop, there is a memory leak.

Yeah, it’s worth checking out the move_*() functions to make sure data is destroyed properly.

The last thing I can think of is your LoadTexture() function. In that function, I assume you load an image with SDL_Image, which is saved into an SDL_Surface, which an SDL_Texture is then created from and that texture is then returned. Make sure that the temporary data in that function is properly destroyed, for example the SDL_Surface.

Hey, I think I found the issue. I am somehow loading images in my carouselCardImages[] vector every frame. I’m not sure how my code is doing that right now but I am trying to figure out why. My carouselCardImages array is getting huge and growing at a rate of y = x. At least its linear…lol.

I found the reason why carouselCardImages was getting so large. My loadTexture function was appending any texture to the end of my carouselfCardImages array where I used it. I was using it very specifically at first but later I realized I could use it a lot more generally but forgot to take out the line to append whatever texture it gets to carouselCardImages. Everywhere I used it, it was putting that image onto my array. It stays at size 14 now instead of growing by hundreds every few seconds. Thank you for your feedback.

I was still leaking memory because when assigning a value to a vector, it allocates memory again. I found std::rotate which works very well with my carouselCardImages array and doesn’t allocate any new memory so no memory leak now! Now I have to figure out how to do this with the captions and I’m done. Thank you for your help.

Very nice that you found the solution, good job. Keep up the good work!

One more question. I am getting repeating text when I display text. You can see that I destroy the text surface and texture every game loop.