谈谈open62541 内存泄漏问题

         开发的Open61541 应用程序调试算通过了,使用top 命令监控该软件的性能,结果发现,发现内存会缓慢地增长,直到最后被系统杀死。这是典型的内存泄露(memory leaks)问题。于是下载了专门检测内存泄露的Valgrind 软件。它是一个用于内存调试、内存泄漏检测和性能分析的开源工具。

Valgrind 工具安装

sudo apt  install valgrind

Valgrind  使用

valgrind --tool=memcheck --leak-check=full ./uaForteA

检测的结果有上万个泄漏(definitely lost)的现象!

        但是改了几天,好像没有改善。最后只能一段一段地查找。下面将我去除open62541 内存泄漏的经验分享给大家:

open62541 容易内存泄漏的函数调用

        使用open62541源代码时,需要十分消息内存泄漏问题,而且程序比较复杂时,出现了泄漏比较难查 。基本的原则是,凡是返回一个值的函数,都可能需要UA_clear。 要不然就可能出现泄漏。下面是一些例子:

UA_Server_readValue

    该函数返回的是值的副本,涉及malloc ,需要在使用完成后Free 掉。具体的做法是:

 UA_Variant CV;    
 //读取
UA_Server_readValue(server,CVNodeId,&CV); 
// 清除
UA_clear(&CV,&UA_TYPES[UA_TYPES_VARIANT]);

UA_Variant_setScalarCopy

     这里的Copy是建立了一个副本,必须free,简单的方法是直接改成UA_Variant_setScalar 就好了。

UA_Server_getDataType 

该命令调用UA_Variant_setScalarCopy,所以与UA_Variant_setScalarCopy的情形是一样的。

UA_STRING 

        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_Server_readBrowseName

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_Server_browse

  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

才放心。

你可能感兴趣的:(OPCUA)