I think I found a memory leak in SDL_RenderCopy

I’m new to SDL so I’m not sure if I found a memory leak or if I’m doing something wrong. Basically I’m drawing a grid with 250k tiles.

If I draw in a loop this grid the memory stays at 120mb but if I translate the coordinates of each tile with an offset, as soon as the grid starts to get drawn outside of the window viewport, then the memory grows and grows every frame taking all system memory.

As soon as the program stops moving the grid, then the memory usage stops increasing, but the leaked memory is not released.

Also when the grid goes completely outside of the viewport the memory leak stops.

I’m running this code with macos 10.15.6 and latest SDL 2.0.12

This is the code:

#include <SDL2/SDL.h>

#if SDL_BYTEORDER == SDL_BIG_ENDIAN
Uint32 _rmask = 0xff000000;
Uint32 _gmask = 0x00ff0000;
Uint32 _bmask = 0x0000ff00;
Uint32 _amask = 0x000000ff;
#else
Uint32 _rmask = 0x000000ff;
Uint32 _gmask = 0x0000ff00;
Uint32 _bmask = 0x00ff0000;
Uint32 _amask = 0xff000000;
#endif

int main() {
  SDL_Init(SDL_INIT_EVERYTHING);

  SDL_Window *window = SDL_CreateWindow(
    "memory leak test",
    SDL_WINDOWPOS_CENTERED,
    SDL_WINDOWPOS_CENTERED,
    1280,
    720,
    0);

  SDL_Renderer *renderer =
    SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC);

  SDL_Surface *testSurface =
    SDL_CreateRGBSurface(0, 1, 1, 32, _rmask, _gmask, _bmask, _amask);

  SDL_FillRect(
    testSurface, NULL, SDL_MapRGBA(testSurface->format, 10, 44, 76, 255));

  SDL_Texture *testTexture =
    SDL_CreateTextureFromSurface(renderer, testSurface);

  SDL_Event event;

  int columns = 500;
  int rows = 500;
  double cameraOffsetX = 100.0;
  double cameraOffsetY = 0.0;
  int tileSize = 2;
  bool quit = false;

  while (!quit) {
    while (SDL_PollEvent(&event)) {
      switch (event.type) {
        case SDL_QUIT:
          quit = true;
          break;
        case SDL_KEYDOWN:
          if (event.key.keysym.sym == SDLK_ESCAPE) {
            quit = true;
          }
          break;
      }
    }

    if (cameraOffsetX > -300.0) {
      // Memory starts leaking when tiles are drawn outside of the viewport
      // As soon as the offset stop moving the memory leaking stops
      // This is running SDL 2.0.12 on macOS 10.15.6
      cameraOffsetX -= 1.0;
    }

    SDL_RenderClear(renderer);

    for (int tileX = 0; tileX < columns; tileX++) {
      int x = tileX * tileSize + cameraOffsetX;
      for (int tileY = 0; tileY < rows; tileY++) {
        int y = tileY * tileSize + cameraOffsetY;
        SDL_Rect tilePosition = {x, y, tileSize, tileSize};
        SDL_RenderCopy(renderer, testTexture, NULL, &tilePosition);
      }
    }

    SDL_RenderPresent(renderer);
  }

  SDL_FreeSurface(testSurface);
  SDL_DestroyTexture(testTexture);
  SDL_DestroyRenderer(renderer);
  SDL_DestroyWindow(window);

  SDL_Quit();

  return 0;
}