I am using uamodeler 1.5.0 with c++ code generation templates version 1.5.0 (version 4)
We have some unit test that do certain manipulations of address spaces in single threaded and in multithreaded fashion.
When running the tests under valgrind it turns out they sometimes have memory leaks, especially the multithreaded ones.
After some investigation these problems could be traced back to the fact that the generated code, when instantiating nodes, does not check the status code (return value) of calls to addNodeAndReference on the node manager.
The thing here is: if such calls fail then the ownership of the node has not been moved to the nodemanager and the class that created the node has the responsibility to eventually call releaseReference on the node. I was able to demonstrate this by manually fixing the generated code and running the unit tests again.
So to be a little more specific, the generated code I am talking about here is code such as this:
Code: Select all
void FooTypeBase::initialize()
{
OpcUa_Int16 nsIdx = m_pNodeConfig->getNameSpaceIndex();
UaStatus addStatus;
UaVariant defaultValue;
if ( s_typeNodesCreated == false )
{
createTypes();
}
// Mandatory variable CustomField1
m_pCustomField1 = new OpcUa::PropertyType(this, s_pCustomField1, m_pNodeConfig, m_pSharedMutex);
addStatus = m_pNodeConfig->addNodeAndReference(this, m_pCustomField1, OpcUaId_HasProperty);
UA_ASSERT(addStatus.isGood());
// Mandatory variable CustomField2
m_pCustomField2 = new OpcUa::PropertyType(this, s_pCustomField2, m_pNodeConfig, m_pSharedMutex);
addStatus = m_pNodeConfig->addNodeAndReference(this, m_pCustomField2, OpcUaId_HasProperty);
UA_ASSERT(addStatus.isGood());
There seems to be no other way to clean up nodes that could not be added to the address space, other than fixing the generated code. We have attempted to create a cleanup method that searches the address space to remove such "dangling nodes" but we haven't found a way and perhaps it is impossible.
So my question is, could you please, in some newer version of the uamodeler, update the templates such that these error codes are handled and nodes are eventually cleaned up ?
A suggestion I have for this is to, for every created class, keep flags around that indicate if the original addition of the node failed or succeeded, then in the destructor, check for every subnode if the original addition failed and release the reference in that case. This will still lead to a badly functioning address space, but at least the memory leaks will be dealt with. I would also suggest to have getters for every subnode flag so that calling code can detect that object creating did not fully succeed and can do extra error handling. Then something like an isValid method would be needed also that returns false if any of the subnode addition failed.
I hope I have stated my problem clear enough, if you have any more questions, please reply and please consider improving the generated code templates.
Kind regards,
Lambert Duijst