How to deallocate userdata?

How do I deallocate any heap allocated userdata I set?

// bank used here as an example, but this could be anything
Bank* bank;

UserData* userData = new UserData;
// how do I free this?
bank->setUserData(userData);

All the examples I can find involve setting userdata to a value on the stack, nothing that uses new or malloc.

Hello, if you don’t have access to userData when freeing, you could retrieve the pointer with Bank::getUserData and call delete on it after casting it back to UserData *.

Something like this should work:

UserData *data;
FMOD_RESULT result = bank->getUserData((void **)&data);
if (result == FMOD_OK)
{
    delete data;
}
else
{
    // error
}

How do I know when a bank (or any other object with associated userdata) is about to be released, so I can also deallocate the userdata associated with it?

You could add a callback with FMOD::System::setCallback that checks for the callback type FMOD_STUDIO_SYSTEM_CALLBACK_BANK_UNLOAD.

This callback passes the handle of the bank where you can get and deallocate the user data.

Unless there’s a strong reason not to, I’d probably just make a class that wraps the bank + userdata and handles unloading/deallocating without needing callbacks.

1 Like

Alright! I’ll try that, although I am a little worried about potential use after frees.

1 Like

Besides what @aishi1 has already mentioned with regards to knowing when to release user data - to safely deallocate user data, set the user data to nullptr or equivalent with setUserData(), and then free your memory. User data isn’t touched by FMOD, except for when using FMOD_STUDIO_BANK_INFO, where a non-zero userdatalength will cause FMOD to copy the data from your pointer to internal memory.

So far I’ve gotten this strategy to (mostly) work, until I tried deallocating userdata attached to event descriptions. My code roughly looks like this:

FMOD_RESULT deallocate_bank(Bank bank)  {
    void* userdata;
    bank.get_userdata(&userdata);

    // deallocate the userdata if it is not null
    if userdata {
       delete (InternalBankUserdata*) userdata;
       bank.set_userdata(NULL);
    }

    std::vector<EventDescription> list = get_event_list(bank);
    for (EventDescription event : list) {
        event.get_userdata(&userdata);

        // deallocate the userdata if it is not null
        if userdata {
           delete (InternalEventUserdata*) userdata;
           event.set_userdata(NULL);
        }
    }

    return FMOD_OK;
}

deallocate_bank is called from a system callback, per aishi1’s solution.
My get_event_list function uses Bank::get_event_count and Bank::get_event_list to get the list of all event descriptions. When I call either function though, they just return FMOD_ERR_NOTREADY. What should I do?

At the point where FMOD_STUDIO_SYSTEM_CALLBACK_BANK_UNLOAD fires, the bank has already been unloaded, and all resources freed. As a result, you won’t be able to iterate over the bank’s event descriptions from the callback - you’ll need to do that before unloading the bank.