How to perform deep copy using double poiners?

574 views Asked by At

Question read.

In the below code, List used by Stack in-turn used by preOrderTraversal(), of rooted tree, without recursion but using explicit stack, /* list.h */ typedef struct List{

    void **array;
    int lastItemPosition;
    int size;
  }List;

  #define INITIAL_LIST_SIZE 50

List *createList(List *list, Op opType){

  List *lptr = (List *)malloc(sizeof(List));
  void *array = NULL;
  if(opType == CREATE_NEW_LIST){

    array = malloc(INITIAL_LIST_SIZE*sizeof(void*));
    lptr->array = &array;
    lptr->array = memset(lptr->array, 0, INITIAL_LIST_SIZE*sizeof(void *));
    lptr->lastItemPosition = -1;
    lptr->size = INITIAL_LIST_SIZE;
  }else if(opType == DOUBLE_THE_LIST){

    array = malloc(2*(list->size)*sizeof(void *));
    lptr->array = &array;
    lptr->array = memcpy(lptr->array, list->array, list->size*sizeof(void*));
    lptr->lastItemPosition = list->lastItemPosition;;
    lptr->size = 2*(list->size);
  }else if(opType == HALF_THE_LIST){

    array = malloc(((list->size)/2)*sizeof(void *));
    lptr->array = &array;
    lptr->array = memcpy(lptr->array, list->array, (list->size/2)*sizeof(void *));
    lptr->lastItemPosition = list->lastItemPosition;;
    lptr->size = (list->size)/2;
  }

  return lptr;

}

void insertItem(List *, void *, int);
void *deleteItem(List *, int);
List* createList(List *, Op);

/* Stack.h */
#include"list.h"

typedef struct Stack{

  List *arrayList;
}Stack;

void push(void *);
void *pop();
void*top();

Wrt,

lptr->array = memcpy(lptr->array, list->array, list->size*sizeof(void*));

memcpy is passing double pointers. A double pointer is a single pointer to single pointer, so it can be passed to a function that expects a void pointer, But, the actual copy of array of void* should not work

As I actually need to copy the array of void*. if memcpy is called, like,

lptr->array = memcpy(*(lptr->array), *(list->array), list->size*sizeof(void*));

then,

Does memcpy perform copy operation, successfully? How to perform deep copy?

1

There are 1 answers

2
jez On

Your existing memcpy statement copies an array of void * values. Each of those void * presumably points to a different memory block, with some arbitrary contents. memcpy does not do anything with that arbitrary content: all you have done is to create a copy of the list of addresses of those blocks, not copied the blocks themselves.

It is hard to see how you can do anything at all with the underlying content, in the snippet of code that we can see here, and that includes copying it. This is because there is no record of the type or size of the content pointed-to by each void *'.

The suggestion you made:

memcpy(*(lptr->array), *(list->array), list->size*sizeof(void*))

will not work for several reasons. It asks memcpy to take the first void * value (not any of the others - that's one problem), and to look at the underlying memory block to which that first pointer points. It copies a certain amount of memory from the source to the destination block. But you have not mentioned allocating any new memory for the new destination block (thereby changing the value of the destination void * itself), so the source and destination are presumably the same address. That's another problem. Also, it uses the wrong size (size of the overall list of void *s, not the size of the memory block in question). That's yet another problem.

The goal you seem to want to achieve cannot be achieved with a single call. Your void *s may (as defined by code we cannot see here) point to consecutive parts of a single contiguous memory blockā€”in which case a single memcpy might appear to work "by accident". But as far as we know, they also might not be arranged like that. They might be separately-allocated chunks of memory all over the place. If so, you're going to need to treat each one separately: loop over the array of pointers, and for each one malloc new space for the copy of the associated block before copying that block. Of course, both to allocate and to copy, you're going to need to have a record of the size of each block.