Where is the memory leak in how I am rendering text in SDL?

I am building a simulator using SDL. I need to render text to show values of some parameters. The entire thing is stable for hours, unless I start rendering the text data. I cobbled together my method of rendering text from several examples I found around the JuliaVerse but it is leaking somewhere and I can’t figure it out.

The MWE below will freeze at frame 2073 on my machine. It completely repeatable. If I change the number of times the text rendering happens I can control the crash but I can’t get it to go away. It always freezes at about the same number of characters rendered.

I really don’t like the render_text function below but haven’t found a cleaner way.

I am running on MacOS and struggled a bit to get SDL working at all but now it is working well except for this text render issue. Any ideas or trouble shooting techniques would be greatly appreciated.

module SDLTextTest

using SimpleDirectMediaLayer
using SimpleDirectMediaLayer.LibSDL2
using Printf

function render_text(renderer::Ptr{SDL_Renderer}, text::String, font::Ptr{TTF_Font}, color::SDL_Color, x::Int32, y::Int32)
    text_surf = TTF_RenderUTF8_Shaded(font, text, color, SDL_Color(0, 0, 0, 255))
    message_texture::Ptr{SDL_Texture} = SDL_CreateTextureFromSurface(renderer, text_surf)
    text_width = Ref{Cint}(0)
    text_height = Ref{Cint}(0)
    SDL_QueryTexture(message_texture, C_NULL, C_NULL, text_width, text_height)
    title_message_rect = Ref(SDL_Rect(x, y, text_width[], text_height[]))
    SDL_RenderCopy(renderer, message_texture, C_NULL, title_message_rect)
end


function main()

    window_width::Int64 = 1000
    window_height::Int64 = 768

    # These are the screen coordinates of the various viewports


    @assert SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) == 0 "error initializing SDL: $(unsafe_string(SDL_GetError()))"

    win = SDL_CreateWindow("SonarSim", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_width, window_height, SDL_WINDOW_SHOWN)
    SDL_SetWindowResizable(win, SDL_FALSE)

    renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC)

    SDL_RenderSetScale(renderer, 1, 1)

    @assert TTF_Init() == 0 "error initializing SDL_TTF: $(unsafe_string(SDL_GetError()))"
    font = TTF_OpenFont("/System/Library/Fonts/SFNS.ttf", 10)

    frame = 0
    test_string = @sprintf("This string is 34 characters long.")

    try
        close = false
        while !close
            event_ref = Ref{SDL_Event}()
            while Bool(SDL_PollEvent(event_ref))
                evt = event_ref[]
                evt_ty = evt.type
                if evt_ty == SDL_QUIT
                    close = true
                    break
                end
            end


            SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255)
            SDL_RenderClear(renderer)

            # generate lots of random strings
            # ny 40 -> 2073 = 14,096,400 characters
            # ny 30 -> 2760 = 14,076,000 characters
            # ny 20 -> 4129 = 14,028,400 characters


            for nx in 0:5
                for ny in 1:40
                    render_text(renderer, test_string, font, SDL_Color(255, 255, 0, 255), Int32(50 + nx * 150), Int32(10 + 17 * ny))
                end
            end

            s = @sprintf("Frame: %d", frame)
            render_text(renderer, s, font, SDL_Color(255, 255, 0, 255), Int32(10), Int32(10))
            SDL_RenderPresent(renderer)

            frame += 1
        end
    finally
        SDL_DestroyRenderer(renderer)
        SDL_DestroyWindow(win)
        SDL_Quit()
        @printf("\n%d Frames\n", frame)
    end
end

main()
end # module SDLTextTest

Well, crud. 30 seconds after I posted this I figured it out. There are specific calls to free the textures and surfaces in SDL, and I wasn’t doing them.
Adding this

    SDL_DestroyTexture(message_texture)
    SDL_FreeSurface(text_surf)

to render_text fixed the problem.