Memory leak


Having issues with a stateful node developing quite the memory leak. I can’t seem to use VuoRelease() (or VuoRetain()) on floats or integers. I see from Vuo.Math.Count that you use a pointer to the stored value, and creates it as an input. How would I go about solving this when the stored value is not coming from an input, and the instance is a struct instead of a type?

When building the project with retailn/release on these values, I get a warning: incompatible integer to pointer conversion passing ‘VuoInteger’ (aka long long’) to parameter of type ‘const void *’

In the struct, there is also a VuoPoint2d, which retains and releases without any error messages. So I’m clearly doing something wrong when it comes to floats & ints. I suspect I’m passing the value of the VuoReal/-Integer instead of the heap info I’m supposed to pass, but can’t figure out how I’d do it correctly.

Would love some help on this! Cheers!

Floats and integers don’t need to be (and shouldn’t be) retained and released. Only heap-allocated pointers need it.

A few examples of node classes that use struct instance data are, vuo.osc.send, and vuo.scene.twirl. If those don’t answer your question, maybe post some of your code here and I can try to give a more specific answer.

Thank you @jstrecker, I think I might have stumbled onto something else though, causing this kind of behaviour.

I just made a new average list items node to smooth audio ranges a bit, and it just explodes wildly really fast. This node however is a stateless node, and it only gets triggered on start, so although I could be the culprit, I don’t see how.

Here is an image of the Activity Monitor after running the composition for about a minute:

The render scene to image node is there only to get the comp in the dock, as it otherwise wouldn’t even show up. By removing the average list items node, it has a more expected memory usage.

The code for the node:

#include "node.h"
#include "math.h"

                      "title" : "Average List Items",
                      "keywords" : [ "magnitude", "bigger", "smaller", "some", "small", "most", ">", "<", "upper", "range" ],
                      "version" : "2.1.0",
                      "node": {
                          "exampleCompositions" : [ ]

void nodeEvent
        VuoInputData(VuoList_VuoReal) list,
        VuoInputData(VuoInteger) averageOfItems,
        VuoOutputData(VuoList_VuoReal) averageList
    unsigned long listCount = VuoListGetCount_VuoReal(list);
    *averageList = VuoListCreate_VuoReal();

    VuoInteger averageCount = averageOfItems;

    VuoList_VuoReal tempList = VuoListCreateWithCount_VuoReal(averageCount, 0.0);

    for(int i = 1; i <= listCount; i = (i + averageCount)){
        for(int j = 1; j <= VuoListGetCount_VuoReal(tempList); ++j){
            VuoListSetValue_VuoReal(tempList, VuoListGetValue_VuoReal(list, i+ (j - 1)), j, false);
        VuoListAppendValue_VuoReal(*averageList, VuoReal_average(tempList));


The original-problem node takes a relatively long time to reach any significant memory usage, but it still slowly grows out of its expected range, and into problem territory. That would be kind of worse if I hadn’t noticed after running the node for a long time. Still work in progress it lacks defaults and proper naming, but here is the code if there is something glaringly obvious:

#include "node.h"
#include <math.h>

                     "title" : "Grow Real",
                     "description" : "Grows a list of VuoReals from a starting point to an end point.",
					 "keywords" : [ ],
					 "version" : "1.0.0",
					 "dependencies" : [ ],
					 "node": {
						 "isInterface" : false

struct nodeInstanceData
    VuoList_VuoPoint2d instanceTime;
    VuoReal previousTime;
    VuoInteger count;

struct nodeInstanceData * nodeInstanceInit
        VuoInputData(VuoInteger) points
    struct nodeInstanceData * instance = (struct nodeInstanceData *)malloc(sizeof(struct nodeInstanceData));
    VuoRegister(instance, free);

    instance->instanceTime = VuoListCreateWithCount_VuoPoint2d(points, VuoPoint2d_make(0.0, 0.0));
    instance->count = 0;
    instance->previousTime = 0.0;

    return instance;

void nodeInstanceEvent
        VuoInstanceData(struct nodeInstanceData *) instance,
        VuoInputEvent({"eventBlocking":"wall"}) trigger,
        VuoInputData(VuoReal) time,
        VuoInputData(VuoInteger, {"default":100, "suggestedMin":1, "suggestedMax":10000}) points,
        VuoInputData(VuoReal) startPosition,
        VuoInputData(VuoReal) endPosition,
        VuoInputData(VuoReal) duration,
        VuoInputData(VuoCurve) curve,
        VuoInputData(VuoCurveEasing) easing,
        VuoInputData(VuoLoopType) loop,
        VuoOutputData(VuoList_VuoReal) timeList
    //Make the output list

    *timeList = VuoListCreateWithCount_VuoReal(points, 0.0);

    //Make a copy of the info list

    VuoList_VuoPoint2d workList = VuoListCopy_VuoPoint2d((*instance)->instanceTime);

    //Get current count of active items

    VuoInteger activeCount = (*instance)->count;

    //Calculate time interval
    VuoReal pTime = (*instance)->previousTime;
    VuoReal frameTime = time - pTime;

    //Trigger durations

        activeCount += 1;
        if(activeCount > points){
            activeCount = 1;
        VuoListSetValue_VuoPoint2d(workList, VuoPoint2d_make(time,duration), activeCount, false);

    //VuoPoint3d stores curve data as: x = start time, y = duration. Duration decides if it is active or not (switch between durationTime / 0 for off)
    //Calculating the individual point/scale times

    for(unsigned int i = 0; i < points; ++i){
        VuoInteger index = i + 1;

        VuoPoint2d instanceInfo = VuoListGetValue_VuoPoint2d(workList, index);

        VuoReal currentTime = (time - instanceInfo.x) + frameTime;

        VuoReal pointTime = VuoReal_curve(

        if(pointTime == endPosition){
            instanceInfo = VuoPoint2d_make(0,0);
            pointTime = 0.0;


        VuoListSetValue_VuoReal(*timeList, pointTime, index, false);
        VuoListSetValue_VuoPoint2d(workList, instanceInfo, index, false);

    (*instance)->previousTime = time;
    (*instance)->count = activeCount;
    (*instance)->instanceTime = workList;

void nodeInstanceFini
        VuoInstanceData(struct nodeInstanceData *) instance

Both nodes are attached.

Magneson.ListTools.AverageListItems.vuonode (2.28 KB)

Magneson.Time_.TimeList.vuonode (5.38 KB)

Wow, that’s some leak :)

When Average Of Items is 0, the memory skyrockets and the node never outputs an event. If you change Average Of Items to 1, the memory is fine and the node outputs the expected event. I’ll bet the node is stuck in an infinite loop in the case where Average Of Items is 0.

How about here: for(int i = 1; i <= listCount; i = (i + averageCount)) — if averageCount is 0, i never increments.

1 Like

Thank you! I’ll check this :)