Bläddra i källkod

Fix memory leaks and compile errors

Stefan Profanter 7 år sedan
förälder
incheckning
c504699ff2

+ 5 - 3
CMakeLists.txt

@@ -247,10 +247,11 @@ if(UA_ENABLE_DISCOVERY_MULTICAST)
     configure_file("deps/mdnsd/libmdnsd/mdnsd_config.h.in" "${PROJECT_BINARY_DIR}/src_generated/mdnsd_config.h")
 endif()
 
-include_directories(${PROJECT_BINARY_DIR}/src_generated
-                    ${PROJECT_SOURCE_DIR}/include
+include_directories(${PROJECT_SOURCE_DIR}/include
                     ${PROJECT_SOURCE_DIR}/plugins # TODO: discovery depends on the default config
-                    ${PROJECT_SOURCE_DIR}/deps)
+                    ${PROJECT_SOURCE_DIR}/deps
+                    ${PROJECT_BINARY_DIR}
+                    ${PROJECT_BINARY_DIR}/src_generated)
 
 set(exported_headers ${PROJECT_BINARY_DIR}/src_generated/ua_config.h
                      ${PROJECT_SOURCE_DIR}/deps/ms_stdint.h
@@ -473,6 +474,7 @@ add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_namespace0.c
                           ${PROJECT_BINARY_DIR}/src_generated/ua_namespace0.h
                    PRE_BUILD
                    COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset_compiler.py
+                           --internal-headers
                            --generate-ns0
                            --ignore ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/NodeID_NS0_Base.txt
                            --xml ${UA_NAMESPACE0_XML}

+ 2 - 6
examples/server_nodeset.c

@@ -2,10 +2,7 @@
  * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. */
 
 #include <signal.h>
-#include "ua_server.h"
-#include "ua_plugin_log.h"
-#include "ua_log_stdout.h"
-#include "ua_config_default.h"
+#include "open62541.h"
 
 /* Files example_namespace.h and example_namespace.c are created from server_nodeset.xml in the
  * /src_generated directory by CMake */
@@ -21,8 +18,7 @@ static void stopHandler(int sign) {
 int main(int argc, char** argv) {
     signal(SIGINT, stopHandler);
     signal(SIGTERM, stopHandler);
-
-    /* initialize the server */
+    
     UA_ServerConfig *config = UA_ServerConfig_new_default();
     UA_Server *server = UA_Server_new(config);
 

+ 3 - 1
src/server/ua_server_ns0.c

@@ -613,7 +613,9 @@ UA_Server_initNS0(UA_Server *server) {
 
     retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_SERVERPROFILEARRAY,
                                     profileArray, profileArraySize, &UA_TYPES[UA_TYPES_STRING]);
-    UA_Array_delete(profileArray, 4, &UA_TYPES[UA_TYPES_STRING]);
+    for (int i=0; i<4; i++) {
+        UA_String_deleteMembers(&profileArray[i]);
+    }
 
     /* MaxQueryContinuationPoints */
     UA_UInt16 maxQueryContinuationPoints = 0;

+ 4 - 4
src/ua_types_encoding_binary.c

@@ -854,8 +854,8 @@ LocalizedText_decodeBinary(UA_LocalizedText *dst, const UA_DataType *_) {
 
 /* The binary encoding has a different nodeid from the data type. So it is not
  * possible to reuse UA_findDataType */
-static const UA_DataType *
-findDataTypeByBinary(const UA_NodeId *typeId) {
+const UA_DataType *
+UA_findDataTypeByBinary(const UA_NodeId *typeId) {
     /* We only store a numeric identifier for the encoding nodeid of data types */
     if(typeId->identifierType != UA_NODEIDTYPE_NUMERIC)
         return NULL;
@@ -942,7 +942,7 @@ ExtensionObject_encodeBinary(UA_ExtensionObject const *src, const UA_DataType *_
 static status
 ExtensionObject_decodeBinaryContent(UA_ExtensionObject *dst, const UA_NodeId *typeId) {
     /* Lookup the datatype */
-    const UA_DataType *type = findDataTypeByBinary(typeId);
+    const UA_DataType *type = UA_findDataTypeByBinary(typeId);
 
     /* Unknown type, just take the binary content */
     if(!type) {
@@ -1105,7 +1105,7 @@ Variant_decodeBinaryUnwrapExtensionObject(UA_Variant *dst) {
 
     /* Search for the datatype. Default to ExtensionObject. */
     if(encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING &&
-       (dst->type = findDataTypeByBinary(&typeId)) != NULL) {
+       (dst->type = UA_findDataTypeByBinary(&typeId)) != NULL) {
         /* Jump over the length field (TODO: check if length matches) */
         g_pos += 4; 
     } else {

+ 2 - 0
src/ua_types_encoding_binary.h

@@ -39,6 +39,8 @@ UA_decodeBinary(const UA_ByteString *src, size_t *offset, void *dst,
 
 size_t UA_calcSizeBinary(void *p, const UA_DataType *type);
 
+const UA_DataType *UA_findDataTypeByBinary(const UA_NodeId *typeId);
+
 #ifdef __cplusplus
 }
 #endif

+ 2 - 0
tests/CMakeLists.txt

@@ -240,6 +240,7 @@ add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_di.c
                    ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_di.h
                    PRE_BUILD
                    COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset_compiler.py
+                   --internal-headers
                    --types-array=UA_TYPES
                    --types-array=UA_TYPES_DI
                    --existing ${PROJECT_SOURCE_DIR}/tools/schema/namespace0/Opc.Ua.NodeSet2.xml
@@ -263,6 +264,7 @@ add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_adi.c
                    ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_adi.h
                    PRE_BUILD
                    COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset_compiler.py
+                   --internal-headers
                    --types-array=UA_TYPES
                    --types-array=UA_TYPES_DI
                    --types-array=UA_TYPES_ADI

+ 1 - 1
tests/check_nodeset_compiler.c

@@ -42,7 +42,7 @@ END_TEST
 static Suite* testSuite_Client(void) {
     Suite *s = suite_create("Server Nodeset Compiler");
     TCase *tc_server = tcase_create("Server DI and ADI nodeset");
-    tcase_add_checked_fixture(tc_server, setup, teardown);
+    tcase_add_unchecked_fixture(tc_server, setup, teardown);
     tcase_add_test(tc_server, Server_addDiNodeset);
     tcase_add_test(tc_server, Server_addAdiNodeset);
     suite_add_tcase(s, tc_server);

+ 11 - 5
tools/nodeset_compiler/backend_open62541.py

@@ -153,7 +153,7 @@ def reorderNodesMinDependencies(nodeset):
 # Generate C Code #
 ###################
 
-def generateOpen62541Code(nodeset, outfilename, supressGenerationOfAttribute=[], generate_ns0=False, typesArray=[]):
+def generateOpen62541Code(nodeset, outfilename, supressGenerationOfAttribute=[], generate_ns0=False, internal_headers=False, typesArray=[]):
     outfilebase = basename(outfilename)
     # Printing functions
     outfileh = open(outfilename + ".h", r"w+")
@@ -179,7 +179,9 @@ def generateOpen62541Code(nodeset, outfilename, supressGenerationOfAttribute=[],
 
 #ifndef %s_H_
 #define %s_H_
-
+""" % (outfilebase.upper(), outfilebase.upper()))
+    if internal_headers:
+        writeh("""
 #ifdef UA_NO_AMALGAMATION
 #include "ua_types.h"
 #include "ua_server.h"
@@ -188,12 +190,16 @@ def generateOpen62541Code(nodeset, outfilename, supressGenerationOfAttribute=[],
 #else
 #include "open62541.h"
 #endif
-    
+""" % (additionalHeaders))
+    else:
+        writeh("""
+#include "open62541.h"
+""")
+    writeh("""
 extern UA_StatusCode %s(UA_Server *server);
 
 #endif /* %s_H_ */""" % \
-           (outfilebase.upper(), outfilebase.upper(), additionalHeaders,
-            outfilebase, outfilebase.upper()))
+           (outfilebase, outfilebase.upper()))
 
     writec("""/* WARNING: This is a generated file.
  * Any manual changes will be overwritten. */

+ 11 - 6
tools/nodeset_compiler/backend_open62541_nodes.py

@@ -119,6 +119,7 @@ def generateVariableNodeCode(node, nodeset):
     if node.valueRank > 0:
         code.append("attr.arrayDimensionsSize = %d;" % node.valueRank)
         code.append("attr.arrayDimensions = (UA_UInt32 *)UA_Array_new({}, &UA_TYPES[UA_TYPES_UINT32]);".format(node.valueRank))
+        codeCleanup.append("UA_Array_delete(attr.arrayDimensions, {}, &UA_TYPES[UA_TYPES_UINT32]);".format(node.valueRank))
         for dim in range(0, node.valueRank):
             code.append("attr.arrayDimensions[{}] = 0;".format(dim))
 
@@ -210,9 +211,9 @@ def generateExtensionObjectSubtypeCode(node, parent, nodeset, recursionDepth=0,
                 # this is an array
                 code.append(instanceName + "_struct." + subv.alias + "Size = " + str(len(subv)) + ";")
                 code.append(
-                    instanceName + "_struct." + subv.alias + " = (UA_" + subv.__class__.__name__ +
-                    " *) UA_malloc(sizeof(UA_" + subv.__class__.__name__ + ")*" + str(
-                        len(subv)) + ");")
+                     "{0}_struct.{1} = (UA_{2}*) UA_malloc(sizeof(UA_{2})*{3});".format(
+                         instanceName, subv.alias, subv.__class__.__name__, str(len(subv))))
+                codeCleanup.append("UA_free({0}_struct.{1});".format(instanceName, subv.alias))
                 logger.debug("Encoding included array of " + str(len(subv)) + " values.")
                 for subvidx in range(0, len(subv)):
                     subvv = subv[subvidx]
@@ -223,8 +224,10 @@ def generateExtensionObjectSubtypeCode(node, parent, nodeset, recursionDepth=0,
             else:
                 code.append(instanceName + "_struct." + subv.alias + "Size = 1;")
                 code.append(
-                    instanceName + "_struct." + subv.alias + " = (UA_" + subv.__class__.__name__ +
-                    " *) UA_malloc(sizeof(UA_" + subv.__class__.__name__ + "));")
+                    "{0}_struct.{1} = (UA_{2}*) UA_malloc(sizeof(UA_{2}));".format(
+                        instanceName, subv.alias, subv.__class__.__name__))
+                codeCleanup.append("UA_free({0}_struct.{1});".format(instanceName, subv.alias))
+
                 code.append(instanceName + "_struct." + subv.alias + "[0]  = " +
                             generateNodeValueCode(subv, instanceName, asIndirect=True) + ";")
 
@@ -394,10 +397,12 @@ def generateValueCode(node, parentNode, nodeset, bootstrapping=True):
             else:
                 code.append("UA_" + node.value[0].__class__.__name__ + " *" + valueName + " =  UA_" + node.value[
                     0].__class__.__name__ + "_new();")
-                code.append("*" + valueName + " = " + generateNodeValueCode(node.value[0], instanceName) + ";")
+                code.append("*" + valueName + " = " + generateNodeValueCode(node.value[0], instanceName, asIndirect=True) + ";")
                 code.append(
                         "UA_Variant_setScalar( &attr.value, " + valueName + ", " +
                         getTypesArrayForValue(nodeset, node.value[0]) + ");")
+                codeCleanup.append("UA_{0}_delete({1});".format(
+                    node.value[0].__class__.__name__, valueName))
     return [code, codeCleanup]
 
 def generateMethodNodeCode(node):

+ 6 - 1
tools/nodeset_compiler/nodeset_compiler.py

@@ -51,6 +51,11 @@ parser.add_argument('--generate-ns0',
                     dest="generate_ns0",
                     help='Omit some consistency checks for bootstrapping namespace 0, create references to parents and type definitions manually')
 
+parser.add_argument('--internal-headers',
+                    action='store_true',
+                    dest="internal_headers",
+                    help='Include internal headers instead of amalgamated header')
+
 parser.add_argument('-b', '--blacklist',
                     metavar="<blacklistFile>",
                     type=argparse.FileType('r'),
@@ -176,5 +181,5 @@ ns.allocateVariables()
 
 # Create the C code with the open62541 backend of the compiler
 logger.info("Generating Code")
-generateOpen62541Code(ns, args.outputFile, args.suppressedAttributes, args.generate_ns0, args.typesArray)
+generateOpen62541Code(ns, args.outputFile, args.suppressedAttributes, args.generate_ns0, args.internal_headers, args.typesArray)
 logger.info("NodeSet generation code successfully printed")