I'm having a problem with the release version of my program. When I start it on my computer, everything works fine. There are no exceptions, no problems or any other stuff that stops me from working with the program. As soon as I zip the exe and its required DLLs and send it to a friend, he instantly receives the error ".exe has stopped working" when he tries to run the server.
By the way it's an opc server built with "open62541". When running, it retrieves values out of a PLC by the use of a library called "Snap7". And yes, he's located in the same network as I am, hence the reason cannot be the network connection.
We both are using windows and my IDE is Visual Studio 2015. Unfortunately, I cannot really post any code here because it's way too much. Moreover I wouldn't really know which code to post since I don't know where and why the error comes up.
EDIT: Here's my code where I get the exception. It's always thrown when "UA_Server_addVariableNode" is called.
for (int i = 0; i < 4; ++i)
{
UA_VariableAttributes attrAttr;
UA_VariableAttributes_init(&attrAttr);
UA_QualifiedName attrBrowseName;
UA_QualifiedName_init(&attrBrowseName);
switch (i)
{
case 0: //Setting the ip-address
UA_Variant_setScalar(&attrAttr.value, &UA_STRING(currentPlc.ip), &UA_TYPES[UA_TYPES_STRING]);
attrAttr.displayName = UA_LOCALIZEDTEXT("en_US", "IPAddress");
attrBrowseName = UA_QUALIFIEDNAME(1, "IPAddress");
//Add the PLC value to the PLC-ObjectType
UA_Server_addVariableNode(server, UA_NODEID_NULL, newPlcId,
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
attrBrowseName,
UA_NODEID_NULL, attrAttr, NULL, &isAvailableNodeId);
break;
case 1: //Setting the rack
UA_Variant_setScalar(&attrAttr.value, ¤tPlc.rack, &UA_TYPES[UA_TYPES_INT32]);
attrAttr.displayName = UA_LOCALIZEDTEXT("en_US", "Rack");
attrBrowseName = UA_QUALIFIEDNAME(1, "Rack");
//Add the PLC value to the PLC-ObjectType
UA_Server_addVariableNode(server, UA_NODEID_NULL, newPlcId,
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
attrBrowseName,
UA_NODEID_NULL, attrAttr, NULL, &isAvailableNodeId);
break;
case 2: //Setting the slot
UA_Variant_setScalar(&attrAttr.value, ¤tPlc.slot, &UA_TYPES[UA_TYPES_INT32]);
attrAttr.displayName = UA_LOCALIZEDTEXT("en_US", "Slot");
attrBrowseName = UA_QUALIFIEDNAME(1, "Slot");
//Add the PLC value to the PLC-ObjectType
UA_Server_addVariableNode(server, UA_NODEID_NULL, newPlcId,
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
attrBrowseName,
UA_NODEID_NULL, attrAttr, NULL, &isAvailableNodeId);
break;
case 3: //Setting "isAvailable" to give information about the PLC's status
UA_Variant_setScalar(&attrAttr.value, &isAvailable, &UA_TYPES[UA_TYPES_BOOLEAN]);
attrAttr.displayName = UA_LOCALIZEDTEXT("en_US", "isAvailable");
attrBrowseName = UA_QUALIFIEDNAME(1, "isAvailable");
//Add the PLC value to the PLC-ObjectType
UA_Server_addVariableNode(server, UA_NODEID_NULL, newPlcId,
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
attrBrowseName,
UA_NODEID_NULL, attrAttr, NULL, &isAvailableNodeId);
break;
}
}
I solved the problem after doing some research inside the "open62541" header.
In case 0 I use the expression "&UA_STRING(currentPlc.ip)" in the "UA_Variant_setScalar" function which I thought returns the equivalent UA_String of "currentPlc.ip".
But it actually returns a temporary object that is deleted after the function is called. As a result, the actual address of the object is null, hence I get an access violation. I simply added one line in which I pass the returned object to a variable and then use the address of the variable.
case 0: //Setting the ip-address
auto value = UA_STRING(currentPlc.ip);
UA_Variant_setScalar(&attrAttr.value, &value, &UA_TYPES[UA_TYPES_STRING]);
attrAttr.displayName = UA_LOCALIZEDTEXT("en_US", "IPAddress");
attrBrowseName = UA_QUALIFIEDNAME(1, "IPAddress");
//Add the PLC value to the PLC-ObjectType
UA_Server_addVariableNode(server, UA_NODEID_NULL, newPlcId,
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
attrBrowseName,
UA_NODEID_NULL, attrAttr, NULL, &isAvailableNodeId);
break;