# realloc a pointer to a pointer

This topic is 3685 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi all. I'm trying to rewrite three similar functions into one generic function. Currently I have something like this that works: (Retyped to summarise, not the full code!)
#define GROWSIZE 100
#define SQL_MAX_QUERY_SIZE 1024

/* This struct is mostly pointless now. I'm fixing a few other bits of code before I do away with it. */
typedef struct {
unsigned char *string;
} SQL_TRANSACTION;

/* For good or bad, these are global */
SQL_TRANSACTION *SQL_inserts = NULL;
unsigned int numInserts = 0;
unsigned int numInsertsAllocated = 0;

SQL_TRANSACTION *SQL_deletes = NULL;
unsigned int numDeletes = 0;
unsigned int numDeletesAllocated = 0;
....


Each SQL_TRANSACTION type has a function like this:
/* Add *string to the inserts array */
if (numInserts == numInsertsAllocated) {
/* Increase the allocations */
numInsertsAllocated += GROWSIZE;

/* I know the return pointer shouldn't be the same pointer passed to realloc, but for now this works and will do! */
SQL_inserts = (SQL_TRANSACTION*) realloc(SQL_inserts, (SQL_MAX_QUERY_SIZE * numInsertsAllocated));
if (SQL_inserts == NULL) {
printf("realloc failed\n");
exit(1);
}
}

/* More code to format the trans->string and
memcpy it to SQL_inserts[numInserts] */

++numInserts;
}


Everything works well like it is, but I want to replace the three functions with one generic function, but I can't work out how to point to the correct array to work with. I have something similar to this:
....
/* Transaction types */
#define SQL_UPDATE 1
#define SQL_INSERT 2
#define SQL_DELETE 3
....
/* transType is one of the above transaction types, passed by the calling function */
void SQL_Addto_Array(unsigned int transType, SQL_TRANSACTION *trans) {
SQL_TRANSACTION **array = NULL; /* Is it correct to use the double ** notation for what I'm trying to do? */
unsigned int *num = NULL;
unsigned int *allocated = NULL;

switch (transType) {
case SQL_UPDATE:
/* Point the pointers to the correct places */
num = &numInserts;
allocated = &numInsertsAllocated;
array = &SQL_inserts; /* Is this incorrect? */
break;
case SQL_INSERT:
....
/* Code for the other types */
....
} /* End switch */

if (*num == *allocated) {
*allocated += SQL_GROWSIZE;

array = (SQL_TRANSACTION*) realloc(array, (SQL_MAX_QUERY_SIZE * (*allocated))); /* I'm fairly certain this is wrong too! */
if (array == NULL) {
printf("realloc failed\n");
exit(1);
}
}

/* More code to format the trans->string */

/* How do I memcpy trans->string now? */
memcpy(array[*num], trans->string, strlen(trans->string)+1); /* Will probably explode the program! (The +1 is to copy the \0 byte) */

++(*num);
}


The above attempt crashes with... *** glibc detected *** ./wiimpdb.x86: realloc(): invalid pointer: 0x080f29f0 *** ... and anything else I've tried has similar results. I don't really understand the use of pointers to pointers, and reading the docs/tutorials I've found online has just confused me more. Whats the correct way to point the array pointer to where it needs to point, and how do I realloc the pointer it points to? *head explodes* [dead] [Edited by - DrTwox on August 16, 2008 12:05:47 AM]

##### Share on other sites
Hey, I'm not sure I have a solution to your problem, but I looked over your code and suggest you look at how you use pointers..

why are 'num' and 'allocated' pointers? Everytime you use them you have to reference (&) them, and I can't see anywhere you actually use their pointed value.

like

unsigned int *num = NULL;
unsigned int *allocated = NULL;

could just be

unsigned int num = 0;
unsigned int allocated = 0;

and then you wouldn't have to reference/dereference them all the time.

e.g.
if (*num == *allocated)
becomes
if( num == allocated)

this should make things simpler at least..

i think the line where you typecast the result of realloc(..) is the problem. Your forcing the result to become a pointer - to a pointer, when it really isn't - because you've declared it as array**. Try declaring 'array' as just a single pointer.

Also SQL_TRANSACTION is already a pointer to a struct, so in your function declaration

it could just be

hope this helps..

##### Share on other sites
Regarding the realloc:

// the originalarray = (SQL_TRANSACTION*) realloc(array, (SQL_MAX_QUERY_SIZE * (*allocated))); /* I'm fairly certain this is wrong too! */// this should work now*array = (SQL_TRANSACTION*) realloc(*array, (SQL_MAX_QUERY_SIZE * (*allocated)));

i.e. reallocate where the "array" actually points to

##### Share on other sites
Quote:
 Original post by supamikewhy are 'num' and 'allocated' pointers? Everytime you use them you have to reference (&) them, and I can't see anywhere you actually use their pointed value.

In the (switch) statement:
num = &numInserts;
allocated = &numInsertsAllocated;

Depending on the transType value they could also point to numUpdates and numUpdatesAllocated or numDeletes and numDeletesAllocated. If I want to add another transaction array, they would point the appropriate values for it too.
Quote:
 i think the line where you typecast the result of realloc(..) is the problem. Your forcing the result to become a pointer - to a pointer, when it really isn't - because you've declared it as array**. Try declaring 'array' as just a single pointer.

In the working code with the three separate functions for each array, SQL_inserts, SQL_updates or SQL_deletes, the realloc call "grows" each array as needed, and it works well (tested up to about 8500 elements each). If I want to replace those three functions with one more generic function, how do I still keep the three (or more in the future) SQL_ arrays separated? If I just use that one single pointer, I wouldn't have three arrays anymore would I? Which is why I thought I needed the pointer to a pointer. Feel free to kick me for each time I'm wrong :)
Quote:
 Also SQL_TRANSACTION is already a pointer to a struct, so in your function declarationSQL_Addto_Array(unsigned int transType, SQL_TRANSACTION *trans) it could just beSQL_Addto_Array(unsigned int transType, SQL_TRANSACTION trans) hope this helps..

Cool, thanks!

Quote:
 Original post by plastique// this should work now*array = (SQL_TRANSACTION*) realloc(*array, (SQL_MAX_QUERY_SIZE * (*allocated)));

Yes, it does work! (By work I mean compile without complaint and not crash on that line anymore :) ) How do I memcpy into the array as well?
memcpy(array[*num], trans->string, sizeof(trans->string)+1); seems to work for the first call to the function, then segfaults on the second.

##### Share on other sites
I was mainly commenting on the realloc. But anyway, I just went through the whole code now and i can confirm (as the other guy already mentioned) that you need to also allocate extra memory for the strings, so basically

- allocate an array of SQL_TRANSACTION, i.e. x times sizeof(SQL_TRANSACTION), x seems to be "numInsertsAllocated" here
- for each (new) x, allocate an array of y count unsigned chars (y seems to be SQL_MAX_QUERY_SIZE here)

then you can do the memory copy like e.g.
memcpy((*array)[*num].string, trans->string, SQL_MAX_QUERY_SIZE);

##### Share on other sites
Thanks to both of you for you suggestions and help. I've got something that works now. I think the code is long overdue for a cleanup! Hopefully I wont break anything. [smile]

1. 1
2. 2
3. 3
frob
20
4. 4
Rutin
20
5. 5

• 32
• 13
• 10
• 11
• 9
• ### Forum Statistics

• Total Topics
632561
• Total Posts
3007087

×