0

I have a struct containing dynamic struct arrays:

struct C_Node {
    int id;
    int num_children;
    int* children;
};

struct C_Transition {
    int id;
    int duration;
    int num_parents;
    int num_children;
    int* parents;
    int* children;
};

struct C_PetriNet {
    int num_nodes;
    int num_transitions;

    C_Node* nodes;
    C_Transition* transitions;
};

I want to initialize and return the outer struct like the following:

C_PetriNet* Cpp_C_interface::convert_PetriNet(PetriNet petriNet) {
    int num_nodes = static_cast<int>(petriNet.nodes.size());
    int num_transitions = static_cast<int>(petriNet.transitions.size());

    C_PetriNet* c_petriNet = (C_PetriNet*)malloc(sizeof(C_PetriNet));
    C_Node* c_nodes = new C_Node[num_nodes];
    C_Transition* c_transitions = new C_Transition[num_transitions];

    for (int i = 0; i < num_nodes; i++) {
        c_nodes[i].id = petriNet.nodes[i].id;
        c_nodes[i].num_children = petriNet.nodes[i].childs.size();
        c_nodes[i].children = petriNet.nodes[i].childs.data();
    }

    for (int i = 0; i < num_transitions; i++) {
        c_transitions[i].id = petriNet.transitions[i].id;
        c_transitions[i].duration = petriNet.transitions[i].duration;
        c_transitions[i].num_parents = petriNet.transitions[i].parents.size();
        c_transitions[i].num_children = petriNet.transitions[i].childs.size();
        c_transitions[i].children = petriNet.transitions[i].childs.data();
        c_transitions[i].parents = petriNet.transitions[i].parents.data();
    }

    c_petriNet->num_nodes = num_nodes;
    c_petriNet->num_transitions = num_transitions;
    c_petriNet->nodes = c_nodes;
    c_petriNet->transitions = c_transitions;

    return c_petriNet;
};

And use it in the main:

C_PetriNet* c_petriNet;
c_petriNet = Cpp_C_interface::convert_PetriNet(petriNet);
std::cout << "Test out: " << c_petriNet->num_nodes << std::endl;
std::cout << "Test out: " << c_petriNet->nodes[5].children[8] << std::endl;
std::cout << "Test out: " << c_petriNet->transitions[68].parents[1] << std::endl;

However, only the first output (num_nodes) is correct. If I print inside the function before returning, everything works fine. What can I do to return also the dynamic allocated memory?

7
  • new in C?.. Commented Dec 28, 2017 at 20:38
  • Yes unfortunately. By now I never had to care about the allocation on my own. Commented Dec 28, 2017 at 20:44
  • mixing c and c++ code. Commented Dec 28, 2017 at 20:45
  • It’s a bigger software mostly written in C++, but some parts need to be passed through CUDA kernels, hence C Commented Dec 28, 2017 at 20:50
  • What is the incorrect output? Commented Dec 28, 2017 at 21:06

1 Answer 1

1

The problem is that petriNet is a local copy of the object that was passed to your function. You're saving pointers to the data() of various vectors in petriNet in the new C_Node and C_Transition that you're creating, but these pointers become invalid when the function returns.

If you change your function to take a reference, the pointers will remain valid as long as the caller's object is alive, but that's still fragile. What you really need to do is make copies of all the data. So you can use memcpy():

memcpy(c_nodes[i].children, petriNet.nodes[i].childs.data(), c_nodes[i].num_children * sizeof(*petriNet.nodes[i].childs.data());
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.