SDK: 1.13.2 C-API strdup() & realloc(); corrupts heap

Linux / C-API / PlaydateSDK-1.13.2

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. :sob:

Oh, and here's a Valgrind suppression list for the simulator. I didn't bother giving the rules "proper" names, since I just wanted them to go away.

Save this as pds.supp (or whatever), and use it with Valgrind:

valgrind --suppressions=../pds.supp   /home/sando/Code/Play.Date/PlaydateSDK/bin/PlaydateSimulator myApp.pdx

pds.supp:

{
   PDS_wmemcmp_avx2_movbe1
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNKSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE7compareEPKw
   fun:_ZN10wxFileName9NormalizeEiRK8wxString12wxPathFormat
   fun:MakeAbsolute
   fun:_ZN12SimulatorApp6OnInitEv
   fun:_Z7wxEntryRiPPw
   fun:main
}
{
   PDS_wmemcmp_avx2_movbe2
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNK8wxString7compareERKS_
   fun:_ZN10wxUILocale15InitLanguagesDBEv
   fun:_ZN10wxUILocale16FindLanguageInfoERK13wxLocaleIdent
   fun:_ZNK10wxUILocale18GetLayoutDirectionEv
   fun:_ZN8wxWindow18SetLayoutDirectionE17wxLayoutDirection
   fun:_ZN8wxWindow12PostCreationEv
   fun:_ZN19wxTopLevelWindowGTK6CreateEP8wxWindowiRK8wxStringRK7wxPointRK6wxSizelS4_
   fun:wxFrame
   fun:_ZN9MainFrameC1ERK8wxStringS2_
   fun:_ZN12SimulatorApp6OnInitEv
   fun:_Z7wxEntryRiPPw
   fun:main
}
{
   PDS_wmemcmp_avx2_movbe3
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNK8wxString7compareERKS_
   fun:_ZN10wxUILocale15InitLanguagesDBEv
   fun:_ZN10wxUILocale16FindLanguageInfoERK13wxLocaleIdent
   fun:_ZNK10wxUILocale18GetLayoutDirectionEv
   fun:_ZN8wxWindow18SetLayoutDirectionE17wxLayoutDirection
   fun:_ZN8wxWindow12PostCreationEv
   fun:_ZN19wxTopLevelWindowGTK6CreateEP8wxWindowiRK8wxStringRK7wxPointRK6wxSizelS4_
   fun:wxFrame
   fun:_ZN9MainFrameC1ERK8wxStringS2_
   fun:_ZN12SimulatorApp6OnInitEv
   fun:_Z7wxEntryRiPPw
   fun:main
}
{
   PDS_wmemcmp_avx2_movbe4
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNK8wxString7compareERKS_
   fun:_ZN14wxTranslations21GetUntranslatedStringERK8wxString
   fun:_ZN18wxAcceleratorEntry10ParseAccelERK8wxStringPiS3_
   fun:_ZN18wxAcceleratorEntry6CreateERK8wxString
   fun:_ZNK14wxMenuItemBase8GetAccelEv
   fun:_ZN12_GLOBAL__N_18GtkAccelC1EPK10wxMenuItem
   fun:_ZN10wxMenuItem11SetGtkLabelEv
   fun:_ZN6wxMenu9GtkAppendEP10wxMenuItemi
   fun:_ZN6wxMenu8DoAppendEP10wxMenuItem
   fun:_ZN9MainFrameC1ERK8wxStringS2_
   fun:_ZN12SimulatorApp6OnInitEv
}
{
   PDS_wmemcmp_avx2_movbe5
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNK8wxString7compareERKS_
   fun:_ZN14wxTranslations21GetUntranslatedStringERK8wxString
   fun:_ZN18wxAcceleratorEntry10ParseAccelERK8wxStringPiS3_
   fun:_ZN18wxAcceleratorEntry6CreateERK8wxString
   fun:_ZNK14wxMenuItemBase8GetAccelEv
   fun:_ZN12_GLOBAL__N_18GtkAccelC1EPK10wxMenuItem
   fun:_ZN10wxMenuItem11SetGtkLabelEv
   fun:_ZN6wxMenu9GtkAppendEP10wxMenuItemi
   fun:_ZN6wxMenu8DoAppendEP10wxMenuItem
   fun:AppendRadioItem
   fun:_ZN9MainFrameC1ERK8wxStringS2_
   fun:_ZN12SimulatorApp6OnInitEv
}
{
   PDS_wmemcmp_avx2_movbe6
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNK8wxString7compareERKS_
   fun:_ZN14wxTranslations21GetUntranslatedStringERK8wxString
   fun:_ZN18wxAcceleratorEntry10ParseAccelERK8wxStringPiS3_
   fun:_ZN18wxAcceleratorEntry6CreateERK8wxString
   fun:_ZNK14wxMenuItemBase8GetAccelEv
   fun:_ZN12_GLOBAL__N_18GtkAccelC1EPK10wxMenuItem
   fun:_ZN10wxMenuItem11SetGtkLabelEv
   fun:_ZN6wxMenu9GtkAppendEP10wxMenuItemi
   fun:_ZN6wxMenu8DoAppendEP10wxMenuItem
   fun:AppendRadioItem
   fun:_ZN9MainFrameC1ERK8wxStringS2_
   fun:_ZN12SimulatorApp6OnInitEv
}
{
   PDS_TextColour
   Memcheck:Cond
   fun:_ZN8pdButton15UpdateTintImageEv
   fun:SetTextColor
   fun:_ZN12ConsoleFrameC1EP8wxWindow
   fun:_ZN9MainFrame17SetupConsoleFrameEv
   fun:_ZN9MainFrameC1ERK8wxStringS2_
   fun:_ZN12SimulatorApp6OnInitEv
   fun:_Z7wxEntryRiPPw
   fun:main
}
{
   PDS_wmemcmp_avx2_movbe7
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNKSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE7compareEPKw
   fun:_ZNK8wxString7compareEPKc
   fun:_ZNK14wxLogFormatter6FormatEmRK8wxStringRK15wxLogRecordInfo
   fun:_ZN5wxLog11DoLogRecordEmRK8wxStringRK15wxLogRecordInfo
   fun:_ZN5wxLog12CallDoLogNowEmRK8wxStringRK15wxLogRecordInfo
   fun:_ZN5wxLog5OnLogEmRK8wxStringRK15wxLogRecordInfo
   fun:DoCallOnLog
   fun:DoCallOnLog
   fun:_ZN8wxLogger5DoLogEPKwz
   fun:Log<char const*>
   fun:_ZN12SimulatorApp6OnInitEv
   fun:_Z7wxEntryRiPPw
   fun:main
}
{
   PDS_wmemcmp_avx2_movbe8
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNKSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE7compareEPKw
   fun:_ZNK8wxString7compareEPKc
   fun:_ZN5wxURI14ParseAuthorityEPKc
   fun:_ZN5wxURI5ParseEPKc
   fun:_ZN5wxURI6CreateERK8wxString
   fun:_ZN5wxURIC1ERK8wxString
   fun:_ZN5PDKWx7Soapbox21ApplicationSoapboxURLEv
   fun:_ZN5PDKWx7SoapboxC1E8wxStringS1_
   fun:_ZN9MainFrame16OnCheckForUpdateER14wxCommandEvent
   fun:_ZN12wxEvtHandler23ProcessEventIfMatchesIdERK21wxEventTableEntryBasePS_R7wxEvent
   fun:_ZN12wxEvtHandler23SearchDynamicEventTableER7wxEvent
}
{
   PDS_wmemcmp_avx2_movbe9
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNKSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE7compareEPKw
   fun:_ZNK8wxString7compareEPKc
   fun:_ZN5wxURI14ParseAuthorityEPKc
   fun:_ZN5wxURI5ParseEPKc
   fun:_ZN5wxURI6CreateERK8wxString
   fun:_ZN5wxURIC1ERK8wxString
   fun:_ZN5PDKWx7Soapbox5EntryEv
   fun:_ZN8wxThread9CallEntryEv
   fun:_ZN16wxThreadInternal12PthreadStartEP8wxThread
   fun:start_thread
   fun:clone
}
{
   PDS_wmemcmp_avx2_movbe10
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNKSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE7compareEPKw
   fun:_ZNK8wxString7compareEPKc
   fun:Cmp
   fun:IsSameAs
   fun:_ZN9MainFrame11OnFirstIdleER11wxIdleEvent
   fun:_ZN12wxEvtHandler23ProcessEventIfMatchesIdERK21wxEventTableEntryBasePS_R7wxEvent
   fun:_ZN12wxEvtHandler23SearchDynamicEventTableER7wxEvent
   fun:_ZN12wxEvtHandler11TryHereOnlyER7wxEvent
   fun:_ZN12wxEvtHandler19ProcessEventLocallyER7wxEvent
   fun:_ZN12wxEvtHandler12ProcessEventER7wxEvent
   fun:_ZN12wxEvtHandler18SafelyProcessEventER7wxEvent
   fun:_ZN12wxWindowBase14SendIdleEventsER11wxIdleEvent
   fun:_ZN7wxFrame14SendIdleEventsER11wxIdleEvent
}


{
   AAA
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNK8wxString7compareERKS_
   fun:_ZN14wxTranslations21GetUntranslatedStringERK8wxString
   fun:_ZL18CompareAccelStringRK8wxStringPKc
   fun:_ZN18wxAcceleratorEntry10ParseAccelERK8wxStringPiS3_
   fun:_ZN18wxAcceleratorEntry6CreateERK8wxString
   fun:_ZNK14wxMenuItemBase8GetAccelEv
   fun:_ZN12_GLOBAL__N_18GtkAccelC1EPK10wxMenuItem
   fun:_ZN10wxMenuItem11SetGtkLabelEv
   fun:_ZN6wxMenu9GtkAppendEP10wxMenuItemi
   fun:_ZN6wxMenu8DoAppendEP10wxMenuItem
   fun:_ZN9MainFrameC1ERK8wxStringS2_
}
{
   AAB
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNK8wxString7compareERKS_
   fun:_ZN14wxTranslations21GetUntranslatedStringERK8wxString
   fun:_ZL18CompareAccelStringRK8wxStringPKc
   fun:_ZN18wxAcceleratorEntry10ParseAccelERK8wxStringPiS3_
   fun:_ZN18wxAcceleratorEntry6CreateERK8wxString
   fun:_ZNK14wxMenuItemBase8GetAccelEv
   fun:_ZN12_GLOBAL__N_18GtkAccelC1EPK10wxMenuItem
   fun:_ZN10wxMenuItem11SetGtkLabelEv
   fun:_ZN6wxMenu9GtkAppendEP10wxMenuItemi
   fun:_ZN6wxMenu8DoAppendEP10wxMenuItem
   fun:_ZN9MainFrameC1ERK8wxStringS2_
}
{
   AAC
   Memcheck:Cond
   fun:_ZN8pdButton15UpdateTintImageEv
   fun:SetImage
   fun:_ZN12ConsoleFrameC1EP8wxWindow
   fun:_ZN9MainFrame17SetupConsoleFrameEv
   fun:_ZN9MainFrameC1ERK8wxStringS2_
   fun:_ZN12SimulatorApp6OnInitEv
   fun:_Z7wxEntryRiPPw
   fun:main
}
{
   AAD
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNKSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE7compareEPKw
   fun:_ZNK8wxString7compareEPKc
   fun:_ZNK14wxLogFormatter6FormatEmRK8wxStringRK15wxLogRecordInfo
   fun:_ZN5wxLog11DoLogRecordEmRK8wxStringRK15wxLogRecordInfo
   fun:_ZN10wxLogChain11DoLogRecordEmRK8wxStringRK15wxLogRecordInfo
   fun:_ZN5wxLog12CallDoLogNowEmRK8wxStringRK15wxLogRecordInfo
   fun:_ZN5wxLog5OnLogEmRK8wxStringRK15wxLogRecordInfo
   fun:DoCallOnLog
   fun:DoCallOnLog
   fun:_ZN8wxLogger5DoLogEPKwz
   fun:Log<wxString>
   fun:_ZN12SimulatorApp6OnInitEv
   fun:_Z7wxEntryRiPPw
   fun:main
}
{
   AAE
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNKSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE7compareEPKw
   fun:_ZNK8wxString7compareEPKc
   fun:_ZN5wxURI9ParsePathEPKc
   fun:_ZN5wxURI5ParseEPKc
   fun:_ZN5wxURI6CreateERK8wxString
   fun:_ZN5wxURIC1ERK8wxString
   fun:_ZN5PDKWx7Soapbox21ApplicationSoapboxURLEv
   fun:_ZN5PDKWx7SoapboxC1E8wxStringS1_
   fun:_ZN9MainFrame16OnCheckForUpdateER14wxCommandEvent
   fun:_ZN12wxEvtHandler23ProcessEventIfMatchesIdERK21wxEventTableEntryBasePS_R7wxEvent
   fun:_ZN12wxEvtHandler23SearchDynamicEventTableER7wxEvent
}
{
   AAF
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNK8wxString7compareERKS_
   fun:_ZN17wxFileConfigEntry8SetValueERK8wxStringb
   fun:_ZN12wxFileConfig13DoWriteStringERK8wxStringS2_
   fun:Write
   fun:Write
   fun:_ZN9MainFrame11OnFirstIdleER11wxIdleEvent
   fun:_ZN12wxEvtHandler23ProcessEventIfMatchesIdERK21wxEventTableEntryBasePS_R7wxEvent
   fun:_ZN12wxEvtHandler23SearchDynamicEventTableER7wxEvent
   fun:_ZN12wxEvtHandler11TryHereOnlyER7wxEvent
   fun:_ZN12wxEvtHandler19ProcessEventLocallyER7wxEvent
   fun:_ZN12wxEvtHandler12ProcessEventER7wxEvent
   fun:_ZN12wxEvtHandler18SafelyProcessEventER7wxEvent
   fun:_ZN12wxWindowBase14SendIdleEventsER11wxIdleEvent
}
{
   AAG
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNK8wxString7compareERKS_
   fun:_ZN15wxHashTableBase8DoDeleteERK8wxStringl
   fun:_ZN11wxClassInfo10UnregisterEv
   fun:_ZN11wxClassInfoD1Ev
   fun:__run_exit_handlers
   fun:exit
   fun:(below main)
}
{
   AAH
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNKSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE7compareEPKw
   fun:_ZN10wxFileName9NormalizeEiRK8wxString12wxPathFormat
   fun:_ZN12wxFileConfigC1ERK8wxStringS2_S2_S2_lRK8wxMBConv
   fun:_ZN12SimulatorApp11SetupConfigEv
   fun:_ZN12SimulatorApp6OnInitEv
   fun:_Z7wxEntryRiPPw
   fun:main
}
{
   AAI
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNKSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE7compareEPKw
   fun:_ZNK8wxString7compareEPKc
   fun:_ZN5wxApp10InitializeERiPPw
   fun:_Z12wxEntryStartRiPPw
   fun:_Z7wxEntryRiPPw
   fun:main
}
{
   AAJ
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNKSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE7compareEPKw
   fun:_ZNK8wxString7compareEPKc
   fun:_ZN5wxApp10InitializeERiPPw
   fun:_Z12wxEntryStartRiPPw
   fun:_Z7wxEntryRiPPw
   fun:main
}
{
   AAK
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNKSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE7compareEPKw
   fun:_ZNK8wxString7compareEPKc
   fun:_ZNK14wxLogFormatter6FormatEmRK8wxStringRK15wxLogRecordInfo
   fun:_ZN5wxLog11DoLogRecordEmRK8wxStringRK15wxLogRecordInfo
   fun:_ZN10wxLogChain11DoLogRecordEmRK8wxStringRK15wxLogRecordInfo
   fun:_ZN5wxLog12CallDoLogNowEmRK8wxStringRK15wxLogRecordInfo
   fun:_ZN5wxLog5OnLogEmRK8wxStringRK15wxLogRecordInfo
   fun:DoCallOnLog
   fun:DoCallOnLog
   fun:_ZN8wxLogger5DoLogEPKwz
   fun:Log<char const*>
   fun:_ZN12SimulatorApp6OnInitEv
   fun:_Z7wxEntryRiPPw
   fun:main
}
{
   AAL
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNKSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE7compareEPKw
   fun:_ZNK8wxString7compareEPKc
   fun:_ZNK14wxLogFormatter6FormatEmRK8wxStringRK15wxLogRecordInfo
   fun:_ZN5wxLog11DoLogRecordEmRK8wxStringRK15wxLogRecordInfo
   fun:_ZN5wxLog12CallDoLogNowEmRK8wxStringRK15wxLogRecordInfo
   fun:_ZN5wxLog5OnLogEmRK8wxStringRK15wxLogRecordInfo
   fun:DoCallOnLog
   fun:DoCallOnLog
   fun:_ZN8wxLogger5DoLogEPKwz
   fun:Log<wxString>
   fun:_ZN12SimulatorApp6OnInitEv
   fun:_Z7wxEntryRiPPw
   fun:main
}
{
   AAM
   Memcheck:Addr32
   fun:__wmemcmp_avx2_movbe
   fun:_ZNKSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE7compareEPKw
   fun:_ZNK8wxString7compareEPKc
   fun:_ZN5wxURI9ParsePathEPKc
   fun:_ZN5wxURI5ParseEPKc
   fun:_ZN5wxURI6CreateERK8wxString
   fun:_ZN5wxURIC1ERK8wxString
   fun:_ZN5PDKWx7Soapbox5EntryEv
   fun:_ZN8wxThread9CallEntryEv
   fun:_ZN16wxThreadInternal12PthreadStartEP8wxThread
   fun:start_thread
   fun:clone
}
1 Like

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.

1 Like

Huh?!

Is there a list of what gets free()d and what gets freed via playdate->system->realloc() then ?

Is there doco on whats outside of "newlib domain" ?

You can turn on malloc pool and look at the Malloc Log window to see what has been malloc'd by the system/your game.

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().

With my tongue firmly in my cheek; I ask...

Now that C23 says realloc( blah, 0 ) is undefined behaviour, will you guys finally add a playdate->system->free( blah ) ?! :wink:

Ref: C23 - cppreference.com (and other places).

You can simply call free() (no struct prefixing) and it maps to playdate->system->realloc( blah, 0 ) already. Same with malloc and realloc.