SDL
SDL copied to clipboard
[SDL2][MacOS] Memory leak when opening a PS4 controller
Hello, there seems to be a memory leak whenever a PS4 controller is connected. The number of leaks increases when I disconnect and reconnect the controller. And using a generic usb controller, there are zero leaks.
Current version of SDL2: 2.30.3 MacOS version: Sonoma 14.4.1, arm64
Here's a minimal example that reproduces the leak. Maybe the problem is in my code.
#include <cstdio>
#include <cstring>
#include <SDL.h>
struct Controller {
Controller() : id(-1), controller(nullptr) { }
int id;
SDL_GameController *controller;
};
int main(int argc, char *argv[])
{
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER) != 0)
{
printf("Failed to initialize SDL2: %s\n", SDL_GetError());
return -1;
}
auto window = SDL_CreateWindow("PS4 Controller Leak Test",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
400, 400, 0);
if (!window)
{
printf("Failed to create window: %s\n", SDL_GetError());
SDL_Quit();
return -1;
}
printf("App initialized\n");
Controller controllers[16] {};
bool isRunning = true;
while (isRunning)
{
SDL_Event e;
while (SDL_PollEvent(&e))
{
switch(e.type)
{
case SDL_CONTROLLERDEVICEADDED:
{
const auto index = e.cdevice.which;
const auto controller = SDL_GameControllerOpen(index);
if (!controller)
{
printf("Failed to open controller at index %d: %s\n",
index, SDL_GetError());
break;
}
const auto id = SDL_JoystickGetDeviceInstanceID(index);
if (id == -1)
{
printf("Failed to get Joystick instance id for controller at index %d: %s\n",
index, SDL_GetError());
break;
}
controllers[index].id = id;
controllers[index].controller = controller;
printf("Opened controller with id: %d\n", id);
} break;
case SDL_CONTROLLERDEVICEREMOVED:
{
const auto id = e.cdevice.which;
for (auto &controller : controllers)
{
if (controller.id == id)
{
if (controller.controller)
{
SDL_GameControllerClose(controller.controller);
controller.controller = nullptr;
controller.id = -1;
printf("Closed controller with id: %d\n", id);
}
break;
}
}
} break;
case SDL_CONTROLLERBUTTONDOWN:
{
const auto id = e.cbutton.which;
for (auto &controller : controllers)
{
if (controller.id == id)
{
printf("Pressed button %d on controller %d\n",
e.cbutton.button, id);
break;
}
}
} break;
case SDL_QUIT:
{
isRunning = false;
} break;
}
}
}
for (auto &controller : controllers)
{
if (controller.controller)
SDL_GameControllerClose(controller.controller);
}
SDL_DestroyWindow(window);
SDL_Quit();
printf("App shutdown complete\n");
return 0;
}
Running the program with MacOS leaks, it shows 5 leaks with a simple program run and quit when the PS4 controller is connected. (More occur when disconnecting and reconnect that controller). There are zero when it is disconnected and never connected when the program is running. The most clear leak points to a call to calloc
in hidapi/mac/hid.c:867, function PLATFORM_hid_open_path