Adding this code at startup (but a strdup() seemingly anywhere will do):
char *copied = strdup( "this is a short string" );
playdate->system->realloc( copied, 0 ); // wish there was a free()
Seems to corrupt the heap. Without these two lines of code, valgrind gives me a perfect report.
As soon as these lines are added, everything goes bad real quick, I did chase it back through at least one version of the SDK (still there), but it worked OK previously... maybe a couple of versions back.
e.g.:
# valgrind --suppressions=../pds.supp /home/sando/Code/Play.Date/PlaydateSDK/bin/PlaydateSimulator
==128635== Memcheck, a memory error detector
==128635== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==128635== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==128635== Command: /home/kingsley/Code/Play.Date/PlaydateSDK/bin/PlaydateSimulator
==128635==
07:10:15: SDK: /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2
07:10:15: Release: 1.13.2
07:10:21: Loading: Turret.pdx/
Loading C API game: Turret.pdx/pdex.so
==128635== Invalid read of size 8
==128635== at 0x512C2B: dlmalloc_usable_size (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x55C081: _free (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x55C42C: pd_free (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x5AB7E0: ext_realloc (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x244D923C: init (main.c:384)
==128635== by 0x244DE305: eventHandler (main.c:1828)
==128635== by 0x56E66E: pd_loadPDX (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x485BB7: MainFrame::LoadPDX(wxFileName const&) (mainframe.cpp:1200)
==128635== by 0x489810: MainFrame::OnFirstIdle(wxIdleEvent&) (mainframe.cpp:940)
==128635== by 0x9F58D0: wxEvtHandler::ProcessEventIfMatchesId(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x9F5D6D: wxEvtHandler::SearchDynamicEventTable(wxEvent&) (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x9F6163: wxEvtHandler::TryHereOnly(wxEvent&) (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== Address 0x486b7508 is 8 bytes before a block of size 23 alloc'd
==128635== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==128635== by 0x9A2960E: strdup (strdup.c:42)
==128635== by 0x244D9214: init (main.c:383)
==128635== by 0x244DE305: eventHandler (main.c:1828)
==128635== by 0x56E66E: pd_loadPDX (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x485BB7: MainFrame::LoadPDX(wxFileName const&) (mainframe.cpp:1200)
==128635== by 0x489810: MainFrame::OnFirstIdle(wxIdleEvent&) (mainframe.cpp:940)
==128635== by 0x9F58D0: wxEvtHandler::ProcessEventIfMatchesId(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x9F5D6D: wxEvtHandler::SearchDynamicEventTable(wxEvent&) (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x9F6163: wxEvtHandler::TryHereOnly(wxEvent&) (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x9F620E: wxEvtHandler::ProcessEventLocally(wxEvent&) (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x9F6310: wxEvtHandler::ProcessEvent(wxEvent&) (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635==
==128635== Invalid read of size 8
==128635== at 0x512C42: dlmalloc_usable_size (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x55C081: _free (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x55C42C: pd_free (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x5AB7E0: ext_realloc (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x244D923C: init (main.c:384)
==128635== by 0x244DE305: eventHandler (main.c:1828)
==128635== by 0x56E66E: pd_loadPDX (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x485BB7: MainFrame::LoadPDX(wxFileName const&) (mainframe.cpp:1200)
==128635== by 0x489810: MainFrame::OnFirstIdle(wxIdleEvent&) (mainframe.cpp:940)
==128635== by 0x9F58D0: wxEvtHandler::ProcessEventIfMatchesId(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x9F5D6D: wxEvtHandler::SearchDynamicEventTable(wxEvent&) (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== by 0x9F6163: wxEvtHandler::TryHereOnly(wxEvent&) (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
==128635== Address 0x486b7558 is 24 bytes after a block of size 48 in arena "client"
==128635==
Someone might want to take a look.
It took me fn()hours to track this down, because like a good engineer, I doubted my own code first.
strdup() would not be using our memory tracking system; since it's part of newlib. So when you free it using our memory system you are then freeing memory we didn't allocate. You should be using free() to free it to keep it the newlib domain.
Any API you use that is pd->* is ours, any standard C API print, -malloc-, -free-, alloca, etc are in newlib. EDIT: with the exceptions: we remap malloc, realloc and free from newlib to our implementations. You can see that in setup.c.
Some more information, in your log from valgrid it looks like malloc() is being reimplemented by valgrid (as expected) here:
==128635== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
But that will mess up our resulting free here:
==128635== by 0x55C42C: pd_free (in /home/kingsley/Code/Play.Date/PlaydateSDK-1.13.2/bin/PlaydateSimulator)
If you want to use Valgrid to check for memory issues you'll have to change this line of code playdate->system->realloc( copied, 0 ); to free(copied). That will allow it to correctly rewrite free() to match the malloc() inside of strdup().