Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replacing realloc (C --> C++)

In an earlier question, I asked about typecasting pointers, but was directed to the better solution of using the C++ allocation system instead of mallocs. (I am converting some C code to C++)

However, I still have an issue with a similar function:

I changed:

tmp = malloc(sizeof(char*) * mtmp); --> tmp = new char*[mtmp];

and

free(tmp) --> delete [] tmp;

However, what do I do with realloc in the following function:

char* space_getRndPlanet (void)
{
   int i,j;
   char **tmp;
   int ntmp;
   int mtmp;
   char *res;

   ntmp = 0;
   mtmp = CHUNK_SIZE;
   //tmp = malloc(sizeof(char*) * mtmp); <-- replaced with line below
   tmp = new char*[mtmp];
   for (i=0; i<systems_nstack; i++)
      for (j=0; j<systems_stack[i].nplanets; j++) {
         if(systems_stack[i].planets[j]->real == ASSET_REAL) {
            ntmp++;
            if (ntmp > mtmp) { /* need more space */
               mtmp += CHUNK_SIZE;
               tmp = realloc(tmp, sizeof(char*) * mtmp); <--- Realloc
            }
            tmp[ntmp-1] = systems_stack[i].planets[j]->name;

I am getting the following error:

error: invalid conversion from 'void*' to 'char**'|

EDIT 2:

Okay, the consensus I am getting is that I should ditch my current solution (which I am open to doing).

Just to make sure that I am understanding correctly, do you guys mean that, instead of an array of pointers to objects, I should just have a vector containing the objects themselves?

like image 850
Biosci3c Avatar asked Oct 06 '10 02:10

Biosci3c


People also ask

What is realloc () in C?

The realloc() function changes the size of a previously reserved storage block. The ptr argument points to the beginning of the block. The size argument gives the new size of the block, in bytes. The contents of the block are unchanged up to the shorter of the new and old sizes.

Does realloc overwrite?

No, the data will be copied for you into the new block that the returned p points at, before the old block is freed. This all happens before realloc returns, so the new p points to your data still.

What is the use of realloc () and free ()?

Size of dynamically allocated memory can be changed by using realloc(). As per the C99 standard: void * realloc ( void *ptr, size_t size); realloc deallocates the old object pointed to by ptr and returns a pointer to a new object that has the size specified by size.

Can realloc change address?

Since realloc may move the allocated memory to a new location, you need to account for this. Show activity on this post. Don't count on it staying at the same address. The system is allowed to move the whole affair to a different address for whatever reason.


3 Answers

C allows void* to be implicitly converted to any pointer. C++ doesn't, so if you're using realloc, you have to cast the result to the appropriate type.

But more importantly, using realloc on a pointer returned by new[] is undefined behavior. And there's no direct C++-style equivalent to realloc.

Your choices are, from least to most idiomatic:

  • Stick to malloc/realloc/free and cast the pointers.
  • Use new[] + delete[] instead of realloc
  • Use std::vector<std::string> instead of managing your own memory.
like image 121
dan04 Avatar answered Oct 03 '22 01:10

dan04


This appears to be an unremarkable array that grows as needed.

Stop using explicit memory allocation, you almost certainly have no need of it. Use std::vector or another of the C++ standard library's dynamic containers that automatically grow as needed for you.

It also looks like you're using null-terminated C-style strings. Why not used std::string instead?

like image 28
Nicholas Knight Avatar answered Oct 03 '22 01:10

Nicholas Knight


In C++ you should not be using arrays (even dynamically allocated).

This has been replaced with std::vector

In C:

char** tmp = (char**)malloc(sizeof(char*) * size);
free(tmp);

// And a correct version of realloc
char** alt = (char**)realloc(sizeof(char*) * newSize);
if (alt)
{
    // Note if realloc() fails then it returns NULL
    // But that does not mean the original object is deallocated.
    tmp = alt;
}

In C++

std::vector<char*>   tmp(size);

// No need for free (destructor does that).
tmp.resize(newSize);
like image 33
Martin York Avatar answered Oct 03 '22 01:10

Martin York