Tutorial: Memory Management

Memory Management

The scripting system of Synthesizer V Studio uses a reference-counting technique to share objects and safely transfer the ownership between the host (which runs native code with hard-coded memory management) and the client (which uses garbage collection).

In most cases, script authors do not need to know the underlying mechanism to write working and memory-safe code as most misuses will be detected by the script environment, causing error messages to pop up, e.g. "failed to access a deleted object". There however could be edge cases that go undetected, and in very rare cases, causing crashes.

Managed and Unmanaged Objects

  • A NestedObject can be garbage-collected (managed) by the client environment if it has no parent, unless it is a top-level host-owned object (e.g. the main project).
  • If a NestedObject has a parent, then it is always unmanaged.

For example, if a NoteGroup is created from a script with a few notes added to it,

  • NoteGroup (managed)
    • Note 1 (unmanaged)
    • Note 2 (unmanaged)
    • Note 3 (unmanaged)
    • Automation 1 (unmanaged)
    • Automation 2 (unmanaged)
    • ...

If the parent NoteGroup gets garbage-collected by the client, the host-side destructor for NoteGroup will be triggered, cleaning up all of its unmanaged children.

If the client environment has a reference to one of the unmanaged notes in the NoteGroup, the reference will be marked as deleted when the unmanaged note gets deleted, that is, either when the parent NoteGroup gets garbage-collected, or when the user explicitly deletes the note. Any attempt to access the invalid reference will be detected and result in an error message "failed to access a deleted 'Note' object".

When the managed NoteGroup is added to a Project, it gets converted into an unmanaged object. This conversion is a simple state change that signals the bypass of garbage collection and does not involve any memory allocation/free/copy.