From e44ff7ff04708c2db399830e2d2edae56b192f57 Mon Sep 17 00:00:00 2001 From: libretroadmin <> Date: Fri, 31 Jul 2026 16:34:35 +0000 Subject: [PATCH] Free the +3 floppy controller on machine shutdown specplus3_765_init() allocates a upd_fdc and stores it in a file-scope pointer. specplus3_shutdown() returned 0 and did nothing else, so nothing ever released it: each machine table build allocated a new one and abandoned the previous. Direct leak of 320 byte(s) in 1 object(s) allocated from: upd_fdc_alloc_fdc fuse/peripherals/disk/upd_fdc.c:387 specplus3_765_init fuse/machines/specplus3.c:151 specplus3_init fuse/machines/specplus3.c:130 machine_add_machine fuse/machine.c:123 Free it in the shutdown hook. Both the +3 and the +3e install that same hook, so machine_end() calls it once per machine; clearing the pointer makes the second call a no-op rather than a double free. With this and the startup-manager registration fix, twenty consecutive load/unload/load cycles complete with no leaks and no sanitiser reports at all. --- fuse/machines/specplus3.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fuse/machines/specplus3.c b/fuse/machines/specplus3.c index 46c8cd4..db834a8 100644 --- a/fuse/machines/specplus3.c +++ b/fuse/machines/specplus3.c @@ -450,6 +450,15 @@ ui_drive_inserted( const ui_media_drive_info_t *drive, int new ) int specplus3_shutdown( void ) { + /* specplus3_765_init() allocates this once; nothing released it, so a + second machine table build leaked the previous one. Both the +3 and + the +3e install this hook, so machine_end() calls it twice and it has + to tolerate the second call. */ + if( specplus3_fdc ) { + libspectrum_free( specplus3_fdc ); + specplus3_fdc = NULL; + } + return 0; }