开发的Open61541 应用程序调试算通过了,使用top 命令监控该软件的性能,结果发现,发现内存会缓慢地增长,直到最后被系统杀死。这是典型的内存泄露(memory leaks)问题。于是下载了专门检测内存泄露的Valgrind 软件。它是一个用于内存调试、内存泄漏检测和性能分析的开源工具。
sudo apt install valgrind
valgrind --tool=memcheck --leak-check=full ./uaForteA
检测的结果有上万个泄漏(definitely lost)的现象!
但是改了几天,好像没有改善。最后只能一段一段地查找。下面将我去除open62541 内存泄漏的经验分享给大家:
使用open62541源代码时,需要十分消息内存泄漏问题,而且程序比较复杂时,出现了泄漏比较难查 。基本的原则是,凡是返回一个值的函数,都可能需要UA_clear。 要不然就可能出现泄漏。下面是一些例子:
该函数返回的是值的副本,涉及malloc ,需要在使用完成后Free 掉。具体的做法是:
UA_Variant CV;
//读取
UA_Server_readValue(server,CVNodeId,&CV);
// 清除
UA_clear(&CV,&UA_TYPES[UA_TYPES_VARIANT]);
这里的Copy是建立了一个副本,必须free,简单的方法是直接改成UA_Variant_setScalar 就好了。
UA_Server_getDataType
该命令调用UA_Variant_setScalarCopy,所以与UA_Variant_setScalarCopy的情形是一样的。
UA_STRING 也十分奇葩,没有一种简单的方法实现UA_String 到string 或者 char *的转换。UA_STRING 是一个结构体,包括一个长度和一个字节数组。而且这个字节数组没有字符串结束符('\0‘)。在转换时必须使用malloc ,转换出来的字符串或者char * 需要删除。
char * UA_String2string(UA_String uaString){
char* convert = (char*)UA_malloc(sizeof(char)*uaString.length+1);
memcpy(convert, uaString.data, uaString.length );
convert[uaString.length] = '\0';
return convert;
}
发现返回出去之后,删除不了,最好将这段程序复制到使用的地方。
UA_QualifiedName FbBrowseName; UA_Server_readBrowseName(server,references[i].nodeId.nodeId,&FbBrowseName);
UA_QualifiedName FBTypeBrowseName;
UA_Server_readBrowseName(server,FBTypeNodeId,&FBTypeBrowseName);
iec61499_CreateFB(server,references[i].nodeId.nodeId,FbBrowseName.name,FBTypeBrowseName.name);
UA_clear(&FBTypeBrowseName,&UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
UA_clear(&FbBrowseName,&UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
UA_BrowseDescription bd;
UA_BrowseDescription_init(&bd);
bd.browseDirection=UA_BROWSEDIRECTION_FORWARD;
bd.referenceTypeId=referenceType;
bd.resultMask=UA_BROWSERESULTMASK_ALL;
bd.nodeId=NodeId;
UA_BrowseResult BrowseResult= UA_Server_browse(server,16,&bd);
.......
UA_BrowseResult_clear(&BrowseResult);
在Open62541 中,使用了大量的动态内存分配,要格外地小心内存泄漏问题。由于涉及指针,容易搞错,最好在那里产生了动态分配,就及时删除。
调试的时候,使用Valgrind分段检测。结果
==7133== LEAK SUMMARY:
==7133== definitely lost: 0 bytes in 0 blocks
==7133== indirectly lost: 0 bytes in 0 blocks
==7133== possibly lost: 120 bytes in 5 blocks
==7133== still reachable: 1,640,640 bytes in 16,512 blocks
==7133== suppressed: 0 bytes in 0 blocks
才放心。