Skip to content

Commit

Permalink
Merge pull request #309 from steinbergmedia/memory-leak-detector-macos
Browse files Browse the repository at this point in the history
Memory leak detector macOS: When running a standalone target on macOS with "Malloc Stack Logging" enabled, the target will output all the memory leaks on quit.
  • Loading branch information
scheffle authored Oct 15, 2023
2 parents 4e2c80b + 5f21559 commit 57ce1b8
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 6 deletions.
3 changes: 3 additions & 0 deletions vstgui/contrib/datepicker.mm
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ static void validate (id self, SEL cmd, NSDatePickerCell* datePickerCell,
dateComponents.month = date.month;
dateComponents.year = date.year;
impl->view.dateValue = [calendar dateFromComponents:dateComponents];
#if !__has_feature(objc_arc)
[dateComponents release];
#endif
}

//------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion vstgui/lib/platform/mac/cocoa/nsviewdraggingsession.mm
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ static Class CreateClass ()
//-----------------------------------------------------------------------------
NSImage* NSViewDraggingSession::nsImageForDragOperation (CBitmap* bitmap)
{
return bitmapToNSImage (bitmap);
return [bitmapToNSImage (bitmap) autorelease];
}

//------------------------------------------------------------------------
Expand Down
18 changes: 18 additions & 0 deletions vstgui/standalone/source/platform/mac/macapplication.mm
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,24 @@ - (void)application:(nonnull NSApplication*)sender openFiles:(nonnull NSArray<NS
//------------------------------------------------------------------------
int main (int argc, const char* _Nonnull* _Nonnull argv)
{
#if DEBUG
struct LeakDetector
{
~LeakDetector () noexcept
{
char* env = getenv ("MallocStackLogging");
if (env && (!strcmp (env, "1") || !strcmp (env, "lite")))
{
char command[1024];
pid_t pid = getpid ();
snprintf (command, std::size (command), "leaks %d", pid);
system (command);
}
}
};
static LeakDetector gLeakDetector;
#endif

VSTGUI::init (CFBundleGetMainBundle ());
VSTGUIApplicationDelegate* delegate = [VSTGUIApplicationDelegate new];
[NSApplication sharedApplication].delegate = delegate;
Expand Down
30 changes: 30 additions & 0 deletions vstgui/uidescription/editing/uieditmenucontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ UIEditMenuController::UIEditMenuController (IController* baseController, UISelec
{
}

//------------------------------------------------------------------------
UIEditMenuController::~UIEditMenuController () noexcept
{
if (editMenu)
editMenu->unregisterViewListener (this);
if (fileMenu)
fileMenu->unregisterViewListener (this);
}

//----------------------------------------------------------------------------------------------------
static void addEntriesToMenu (const UIEditing::MenuEntry* entries, COptionMenu* menu, ICommandMenuItemTarget* menuItemTarget, int32_t& index)
{
Expand Down Expand Up @@ -615,6 +624,21 @@ static void copyMenuItems (COptionMenu* src, COptionMenu* dst)
}
}

//------------------------------------------------------------------------
void UIEditMenuController::viewRemoved (CView* view)
{
if (view == editMenu)
{
view->unregisterViewListener (this);
editMenu = nullptr;
}
else if (view == fileMenu)
{
view->unregisterViewListener (this);
fileMenu = nullptr;
}
}

//----------------------------------------------------------------------------------------------------
CView* UIEditMenuController::verifyView (CView* view, const UIAttributes& attributes, const IUIDescription*)
{
Expand All @@ -628,7 +652,10 @@ CView* UIEditMenuController::verifyView (CView* view, const UIAttributes& attrib
if (editMenu)
copyMenuItems (editMenu, menu);
else
{
createEditMenu (menu);
menu->registerViewListener (this);
}
editMenu = menu;
break;
}
Expand All @@ -637,7 +664,10 @@ CView* UIEditMenuController::verifyView (CView* view, const UIAttributes& attrib
if (fileMenu)
copyMenuItems (fileMenu, menu);
else
{
createFileMenu (menu);
menu->registerViewListener (this);
}
fileMenu = menu;
break;
}
Expand Down
9 changes: 7 additions & 2 deletions vstgui/uidescription/editing/uieditmenucontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "../delegationcontroller.h"
#include "../../lib/controls/icommandmenuitemtarget.h"
#include "../../lib/events.h"
#include "../../lib/iviewlistener.h"

namespace VSTGUI {
class IActionPerformer;
Expand Down Expand Up @@ -144,11 +145,14 @@ static const MenuEntry fileMenu[] = {
} // UIEditing

//----------------------------------------------------------------------------------------------------
class UIEditMenuController : public CBaseObject, public DelegationController, public CommandMenuItemTargetAdapter
class UIEditMenuController : public CBaseObject,
public DelegationController,
public CommandMenuItemTargetAdapter,
public ViewListenerAdapter
{
public:
UIEditMenuController (IController* baseController, UISelection* selection, UIUndoManager* undoManager, UIDescription* description, IActionPerformer* actionPerformer);
~UIEditMenuController () noexcept override = default;
~UIEditMenuController () noexcept override;

COptionMenu* getFileMenu () const { return fileMenu; }
COptionMenu* getEditMenu () const { return editMenu; }
Expand All @@ -170,6 +174,7 @@ class UIEditMenuController : public CBaseObject, public DelegationController, pu
void createEditMenu (COptionMenu* menu);
void createFileMenu (COptionMenu* menu);

void viewRemoved (CView* view) override;
CView* verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description) override;
IControlListener* getControlListener (UTF8StringPtr name) override { return this; }
void controlBeginEdit (CControl* pControl) override;
Expand Down
4 changes: 2 additions & 2 deletions vstgui/uidescription/uidescription.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,8 @@ Detail::UINode* UIDescription::findNodeForView (CView* view) const
}

//-----------------------------------------------------------------------------
bool UIDescription::storeViews (const std::list<CView*>& views, OutputStream& stream, UIAttributes* customData) const
bool UIDescription::storeViews (const std::list<CView*>& views, OutputStream& stream,
SharedPointer<UIAttributes> customData) const
{
auto nodeList = makeOwned<Detail::UIDescList> (false);
for (auto& view : views)
Expand Down Expand Up @@ -599,7 +600,6 @@ bool UIDescription::storeViews (const std::list<CView*>& views, OutputStream& st
UINode* customNode = new UINode (Detail::MainNodeNames::kCustom, customData);
nodeList->add (customNode);
customNode->forget ();
customData->remember ();
}
UINode baseNode ("vstgui-ui-description-view-list", nodeList);
return Detail::UIJsonDescWriter::write (stream, &baseNode, false);
Expand Down
3 changes: 2 additions & 1 deletion vstgui/uidescription/uidescription.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ class UIDescription : public NonAtomicReferenceCounted, public IUIDescription
AttributeSaveFilterFunc func = nullptr);
virtual bool saveWindowsRCFile (UTF8StringPtr filename);

bool storeViews (const std::list<CView*>& views, OutputStream& stream, UIAttributes* customData = nullptr) const;
bool storeViews (const std::list<CView*>& views, OutputStream& stream,
SharedPointer<UIAttributes> customData = {}) const;
bool restoreViews (InputStream& stream, std::list<SharedPointer<CView> >& views, UIAttributes** customData = nullptr);

UTF8StringPtr getFilePath () const;
Expand Down

0 comments on commit 57ce1b8

Please sign in to comment.