2

Possible Duplicate:
Copying one structure to another

I have a struct defined as

struct CKTcircuit 
{ 
    more than a 100 pointers and objects of different types  of structure.
    this structure has around 500 lines just declaring variables & pointers.
}

Now I have a object of this type instantiated.

And I have to create a copy this same type.

Any solutions how do I do this?

P.S.: I need to do this because I need to launch another thread doing computations and modifying the CKTcircuit object.

Community
  • 1
  • 1
yashdosi
  • 1,186
  • 1
  • 18
  • 40
  • What type of copy? Deep? – Pubby Nov 03 '12 at 11:35
  • Well then that's going to be a huge pain. Can't use C++? – Pubby Nov 03 '12 at 11:39
  • I suggest implementing a whole layer of reflection on C, something like in Obejctive-C, then enumerating all the fields of a structure and sending them a (polymorphic) `deepCopy` message. Or not. –  Nov 03 '12 at 11:43
  • @Yashdosi - I think that you should divide this structure up in the first place to make it less complicated and more manageable. Have structures declared and defined elsewhere and then use those to built up the higher level sturctures. – Ed Heal Nov 03 '12 at 12:03
  • @EdHeal All that is beyond my control.....I am given an object which is already instantiated and now I have to create a copy of it. And all I am trying to do is to avoid manually creating a copy due to the huge size of the structure. Actually I am not creating a new s/w package...I am editing one. – yashdosi Nov 03 '12 at 12:07
  • @yashdosi That sounds like fun... – leemes Nov 03 '12 at 12:08
  • @leemes It would be fun only if I manage to solve this else I m gonna be in a VERY grave problem. – yashdosi Nov 03 '12 at 12:10
  • 1
    @yashdosi - However this structure is unmanagable now. It might be worthwhile to refactor it. Most code should fit easily on a screen. – Ed Heal Nov 03 '12 at 12:11
  • 1
    What a pain. Is it even safe to copy, with all its pointers/refs to other objects? I do hope that there are not multiple threads using it or its indirected objects. I would do almost anything to avoid a task like this:( – Martin James Nov 03 '12 at 12:34
  • @Pubby What does C++ bring to the table to solve this? – weston Nov 03 '12 at 12:44
  • @MartinJames Thats the whole problem... I need an exact AND DIFFERENT & DISTINCT copy of the original object not just a pointer.. – yashdosi Nov 03 '12 at 12:50
  • 1
    Is there code to free a `CKTcircuit` and it's chain of children stuctures? If not, then maybe the `CKTcircuit` doesn't even "own" the memory, so a clone of these would require such a method to be written to clean up after your calculations. If it does exist it could be a good guide to what needs cloning. – weston Nov 03 '12 at 13:04
  • 1
    get thee to a keyboard and code-editor. There is no magic "find all dynamic allocations in my struct and create deep-copies of them" silver bullet in C. The very fact there is no way to *know* whether a pointer within the struct is referencing dynamic (malloc, calloc, realloc, etc) memory or not makes this hard-by-default. Search all you want, but in the end you will have been better served to spend the day(s) writing a clone-function you *know* is right for your specific application. – WhozCraig Nov 03 '12 at 13:34

2 Answers2

1

What data does your calculations need? Can you create a new struct to hold the data you want then:

struct WorkingData
{ 
    //data needed for calculations
}

struct CKTcircuit source = //whatever;
struct WorkingData work;
CKTcircuit_populateWorkingData(source, &work);
calculate(&work);

Alternatively, use a CKTcircuit for the working data, but be careful to clone structures that contain pointers.

struct CKTcircuit source = //whatever;
struct CKTcircuit work;
CKTcircuit_populateWorkingData(source, &work);
calculate(&work);

But 100 members is not the end of the world:

Might just have to byte the bullet, know the rules and deep clone with an approach like this:

Annotate the members to get an idea of whether each struct is shallow clone OK, or needs deep clone.

struct CKTcircuit 
{ 
    int x; //shallow clone OK
    int *x2; //pointer - needs deep clone
    struct Y y; //shallow clone OK iff members of struct Y are all shallow clone OK
    struct Y *y2; //pointer type, needs deep clone
} //conclusion for this stuct - needs deep clone

struct CKTcircuit CKTcircuit_clone(struct CKTcircuit *source)
{
    struct CKTcircuit result = *source; //shallow clone
    //that has dealt with all value types e.g. ints, floats and
    //even structs that aren't pointed to and don't contain pointers
    //now need to call similar clones functions on all the pointer types
    result.pointerX = &x_clone(source->pointerX);
    return result;
}

You may need custom free methods to free memory if something like this does not exist.

void CKTcircuit_free(struct CKTcircuit *source)
{
    x_free(source->pointerX);
    free(*source);
}
weston
  • 54,145
  • 21
  • 145
  • 203
  • 1
    There may even be some pointers in the structure for which shallow clone is OK/required, for example if the pointer always points to a string literal. So the annotation process is very important, but usually the existing code to free the structure (if any) will help tell you how to write the code to copy the structure. For C++ users this fact is familiar (the Rule of Three). – Steve Jessop Nov 03 '12 at 13:48
0

1) The hard way:

For a deep copy you'll need to traverse the entire structure and recreate it one node at a time. But make sure you use the pointers from the copy and not from the original data structure.

here's a simplified pseudo code example.

node traverse_cp(node, checked_list){
   // makes sure you don't traverse back edges twice. or you'll loop.
   if ( checked_list[node] ) return checked_list[node];


   new_node = copy_node_data(node);
   new_node.left = traverse_cp(node->left, check_list + node);
   new_node.right = traverse_cp(node->right, check_list + node);   
   return node_node;
}

2) Short cuts

A) Contiguous memory If you could guarantee that your memory was contiguously allocated (malloc once and then hand out the memory on your own), then you can just memcpy the whole block and then search for addresses in that address space and just modify them. But, that's not very robust.

B) Array of struct Use a preallocated array of your structures and indices instead of pointers. But that won't work for a heterogenous data structure. This is basically a rewrite of your program.

Gidon Wise
  • 1,896
  • 1
  • 11
  • 11