How to 'Realloc' in C++

realloc an array with c

When you realloc with a smaller size, many implementation just do nothing: you have a bloc that can hold at least 10 elements, it can hold at least 8 elements. Simply you shall no longer use the elements past the declared size. Nothing will prevent you to do it, but it just invokes Undefined Behaviour.

It can be surprising for beginners:

int *arr = malloc(10 * sizeof(int));   // allocate an array of 10 int
for (int i=0; i<10; i++) { // initialize it with 0-9
arr[i] = i;
}
arr = realloc(arr, 8*sizeof(int)); // realloc the array to 8 elements
for (int i=0, i<8; i++) {
printf(" %d", i);
}
printf("\n"); // should have correctly printed 0 1 ... 7
// the interesting part
for (int i=8; i<10; i++) {
printf(" %d", i); // Oops, UB!
}
printf("\n"); // but what is to be expected is just 8 9...

Now it works but is UB. Say differently never pretend that I said that it was correct code. But most implementations will accept it and will give the expected result (which is allowed by UB...) without any other side effect.

using realloc to write on a new string?

For starters your approach is not good.

The function is inefficient because within it there are too many memory reallocations.

As for the messages then this

s = realloc(s, 2 * sizeof(char));

statement is unsafe because the function realloc can return a null pointer. In this case the address of the previously allocated memory will be lost that results in a memory leak.

You need to use an intermediate pointer that will be assigned with the value returned by realloc.

In this statement

s = realloc(s, 2 * sizeof(char));

there are always allocated 2 bytes of memory.

Also there is used an invalid index in the left hand side expression

s[i] = str[i];
^^^^

For the pointer s you need to support its one index not i.

What you need is at first to determine how many there are non-duplicated adjacent characters and then only one time allocate an array of the required size.

Here is a demonstration program.

#include <stdio.h>
#include <stdlib.h>

char * remove_duplicates( const char *s )
{
size_t n = 0;

for ( const char *p = s; *p; )
{
++n;
while ( *++p && p[0] == p[-1] );
}

char *result = malloc( n + 1 );

if ( result != NULL )
{
char *p = result;
do
{
*p = *s;
while ( *s++ && s[0] == s[-1] );
} while ( *p++ );
}

return result;
}

int main( void )
{
const char *s = "1223334444";

printf( "\"%s\"\n", s );

char *p = remove_duplicates( s );

if ( p ) printf( "\"%s\"\n", p );

free( p );
}

The program output is

"1223334444"
"1234"

How to properly realloc a calloc?

The C standard does not provide any routine that performs a reallocation and zeros the additional memory. To achieve this, you can implement it yourself by using realloc to reallocate memory and clearing with memset:

int *newptr = realloc(ptr, 2 * n * sizeof *newptr);
if (!newptr)
{
fprintf(stderr, "Error, unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
ptr = newptr;
memset(ptr + n, 0, n * sizeof *ptr);
n *= 2;

You could of course wrap this into a routine, say one called crealloc, and use that. (Unlike the library functions for memory management, it would have to be passed the size of the prior allocation, since code you write does not ordinarily have access to the memory management data structures that provide that size.)

Proper usage of realloc()

Just don't call free() on your original ptr in the happy path. Essentially realloc() has done that for you.

ptr = malloc(sizeof(int));
ptr1 = realloc(ptr, count * sizeof(int));
if (ptr1 == NULL) // reallocated pointer ptr1
{
printf("\nExiting!!");
free(ptr);
exit(0);
}
else
{
ptr = ptr1; // the reallocation succeeded, we can overwrite our original pointer now
}

How does realloc behave in C++ regarding extra Space?

Here are my suggestions

Why are you speculating about something you can just look up?

For example, the POSIX documentation is here and says the last sixty bytes will be indeterminate.

You can look up the documentation for any platform if you want to know how that platform will behave (and don't care about portability), or you can just assume the values are undetermined.

A) Will be set to 0

Maybe on some platforms, and maybe sometimes on others, but it's not guaranteed.

B) Will Contain garbage from what malloc returned with a new allocation of 100

indeterminate values aren't necessarily garbage - they might all be zero. Or the new memory might be filled with 0xdeadbeef or some other magic value. You just shouldn't depend on any particular value - in fact, you shouldn't read this memory at all until you've written some known values into it.

Actually, I'm not even sure what the second half of that sentence means. The first forty bytes will be whatever you wrote into the original allocation, of course.

C) The first 40 are copied normally and the other 60 are copied too from the memory block after x. (goes out of bound)

That would make realloc illegal to use for its stated purpose, so obviously it can't be true.

The first forty bytes are copied from the old allocation, and you shouldn't depend on the next sixty bytes having any specific value until you put one there yourself.

Realloc variable sized 2D array passed as parameter - C

C passes arguments by value, not by reference. When you pass the obsF pointer to f and reallocate it, you change the value of the obsF parameter in the f function, but the variable in the main function (which determined the parameter's initial value) still holds the old pointer, which has been invalidated by the reallocation.

To fix this, you can pass a pointer to the obsF variable to f, and dereference that pointer to access the variable:

void f(int **obsF)
{
*obsF = realloc(*obsF, sizeof(int[5][2]));
// do stuff with obsF
}

And then call f as:

int main(void)
{
int *obsF = malloc(sizeof(int));
f(&obsF);
free(obsF);
}

This way, the value of the obsF variable inside main will be updated after the call to f and the correct pointer will be freed.



Related Topics



Leave a reply



Submit