Encountered a memory leak related to lv2, so I audited all use of LilvNode and LilvNodes and found the following potential memory leaks:
AudioPluginLV2GUI.cpp:127 node not freed, use lilv_node_free()
const LilvNode *uiUri = lilv_ui_get_uri(m_selectedUI);
AudioPluginLV2GUI.cpp:130 node not freed, use lilv_node_free()
const LilvNode* uib = lilv_ui_get_binary_uri(m_selectedUI);
LV2PluginDatabase.cpp:112 node not freed, use lilv_node_free()
const LilvNode* classLabelNode =
lilv_plugin_class_get_label(pclass);
LV2PluginDatabase.cpp:129 node not freed, use lilv_node_free()
const LilvNode* classUri = lilv_plugin_class_get_uri(pclass);
LV2Utils.cpp:184 lilv_free() used instead of lilv_node_free()
LilvNode* symNode = lilv_new_string(LV2World::get(), portSymbolStr.c_str());
LV2Utils.cpp:418 nodes not freed, use lilv_nodes_free()
LilvNodes* presetNodes = lilv_plugin_get_related(plugin, presetUri);
AudioPluginLV2GUI.cpp:132 return from lilv_file_uri_parse() must be freed
with lilv_free()
QString bpath =
lilv_file_uri_parse(binary_uri.toStdString().c_str(), nullptr);
Please review and fix if appropriate.
OK thanks.
Some of the above calls should not be freed according to the documentation (https://drobilla.net/docs/lilv/).
I have fixed the others.
Is this list manually created or did you use a tool to generate it ?
See merge request.
Last edit: Ted Felix 2025-11-17
Ok. I only saw actual memory leaks with the last two, lilv_plugin_get_related() and lilv_file_uri_parse().
Manually. Wish there were a tool. cppcheck could probably do those kinds of checks pretty easily.
Here is the list above annotated with a sentence from the documentation or fixed
AudioPluginLV2GUI.cpp:127 node not freed, use lilv_node_free()
const LilvNode *uiUri = lilv_ui_get_uri(m_selectedUI);
A shared value which must not be modified or freed.
AudioPluginLV2GUI.cpp:130 node not freed, use lilv_node_free()
const LilvNode* uib = lilv_ui_get_binary_uri(m_selectedUI);
A shared value which must not be modified or freed.
LV2PluginDatabase.cpp:112 node not freed, use lilv_node_free()
const LilvNode* classLabelNode =
lilv_plugin_class_get_label(pclass);
Returned value is owned by plugin_class and must not be freed by caller.
LV2PluginDatabase.cpp:129 node not freed, use lilv_node_free()
const LilvNode* classUri = lilv_plugin_class_get_uri(pclass);
Returned value is owned by plugin_class and must not be freed by caller.
LV2Utils.cpp:184 lilv_free() used instead of lilv_node_free()
LilvNode* symNode = lilv_new_string(LV2World::get(), portSymbolStr.c_str());
fixed
LV2Utils.cpp:418 nodes not freed, use lilv_nodes_free()
LilvNodes* presetNodes = lilv_plugin_get_related(plugin, presetUri);
fixed
AudioPluginLV2GUI.cpp:132 return from lilv_file_uri_parse() must be freed
with lilv_free()
QString bpath =
lilv_file_uri_parse(binary_uri.toStdString().c_str(), nullptr);
fixed
Thanks. I'm going to merge this in shortly, just waiting for higher priority stuff to cool down. I was looking in the header file for documentation and it's incomplete. I'll have a look at the real documentation and refer to it from now on for questions like these.
Docs are silent on lilv_plugin_get_related(). Thankfully ASan isn't.
Pushed as [dc152b]. Please test latest git.
Related
Commit: [dc152b]