0

I have a function which is called several times, with a parameter n which defines the n*2-sized 2d array:

void myfunc(int n){

  static int n0=0,i;
  static double **x=NULL;

  if(n>n0){ //realloc if n grows
    x=(double **)realloc(x,n*sizeof(double*)));
    for(i=0;i<n;i++){
      x[i]=(double *)realloc(x[i],2*sizeof(double))); // <--problem here
    }
    n0=n;
  }

}

At the first call the **x is initialized to NULL, but x[i] are not, and thus the second realloc may behave not correctly.

Is there a way to realloc the rows of an empty 2d matrix, without first using malloc or calloc?

16
  • 2
    A pointer to pointer is not a 2D array. Commented Feb 27, 2018 at 17:14
  • 5
    In C++? Not like that! Please pick one language, C and C++ are two very different languages, and no sane C++ programmer would do something like that. Commented Feb 27, 2018 at 17:14
  • 1
    As for your problem, you do know if the function is called the first time not. Think about what you initialize x to... Commented Feb 27, 2018 at 17:22
  • 1
    The difference is that a 2D array is a contiguous memory region with fixed dimensions. In your case it is pointing to different regions, and each "row" might have a different number of "columns". Commented Feb 27, 2018 at 17:24
  • 1
    In that case, no. realloc only reallocates the memory, it does not initialize otherwise uninitialized parts of the memory. Commented Feb 27, 2018 at 17:27

4 Answers 4

4

Here, you should be using malloc() instead of realloc() since you are not re-allocating memory here.

But if your code can't know if the data is new, it should first be initialized to NULL in order for realloc() to work.

Sign up to request clarification or add additional context in comments.

3 Comments

If myfunc is called multiple times with different values for n, then it's okay IMO. Well, okay if it wasn't full of other problems.
I cannot use malloc because at successive calls would create memory leaks. I need realloc, and I don't know if data is new.
@dude: if you say there are problems please enumerate them
1

I would change the function to use malloc the first time and realloc after that.

However, there is no need to realloc for the current elements of x. You only need to use malloc for the new elements of x.

void myfunc(int n)
{
   static int n0 = 0;
   static double **x = NULL;

   if ( n > n0)
   {
      if ( x == NULL )
      {
         // Use malloc to get memory for x
         x = malloc(n*sizeof(double*));

         for( int i = 0; i < n; i++)
         {
            x[i] = malloc(2*sizeof(double));
         }
      }
      else
      {
         // Use realloc to get more memory for x.
         x = realloc(x, n*sizeof(double*));

         // Allocate memory only for the new elements of x.
         for( int i = n0; i < n; i++)
         {
            x[i] = malloc(2*sizeof(double));
         }
      }

      n0 = n;
   }
}

PS Don't cast the return value of malloc or realloc. See Specifically, what's dangerous about casting the result of malloc? to understand why.


After a little bit of thought, I realized the function can be simplified a bit.

void myfunc(int n)
{
   static int n0 = 0;
   static double **x = NULL;

   if ( n > n0)
   {
      if ( x == NULL )
      {
         // Use malloc
         x = malloc(n*sizeof(double*));
      }
      else
      {
         // Use realloc
         x = realloc(x, n*sizeof(double*));
      }

      // Use malloc for the new elements of x.
      // When n0 is 0, it will be all of them.
      for( int i = n0; i < n; i++)
      {
         x[i] = malloc(2*sizeof(double));
      }

      n0 = n;
   }
}

11 Comments

thanks for your tip about casting. About the solution, then it might be easier to just add a line before the second realloc: if(n0==0) x[i]=NULL;
@cipper, what do you hope to gain from that?
@cipper, see the updated answer. You can decide whether you need to use x[i] = NULL; at all.
@R Sahu: yes, by restricting the loop to n0..n it also solves. Nice idea, thank you!
@R Sahu: but thinking again, after realloc do x[0]..x[n0] remain unchanged? don't they need to be also reallocated?
|
1
void myfunc(int n){

  static int n0=0,i;
  static double **x=NULL;

  if(n>n0){
    x=realloc(x,n*sizeof(double*)));
    for(i=n0;i<n;i++){
      x[i]=malloc(2*sizeof(double)));
    }
    n0=n;
  }

}

Comments

1

In addition to various answer detailing how to increase the allocation, code could be altered to allow an eventual freeing of the allocation by calling with myfunc(0).

Also better to use size_t for array sizing.

No need for i to be static.

This function hides its result, perhaps return the pointer?

double **myfunc(size_t n) {
  static size_t n0 = 0;
  static double **x = NULL;

  if (n > n0) {
    void *new_ptr = realloc(x, sizeof *x * n);
    if (new_ptr == NULL) {
      TBD_Code();  // Handle out-of-memory
    }
    x = new_ptr;
    for (size_t i = n0; i < n; i++) {
      x[i] = malloc(sizeof *(x[i]) * 2);
    }
    n0 = n;
  } else if (n == 0) {
    while (n0 > 0) [
      free(x[--n0]);
    }
    free(x);
    x = NULL;
  }
  return x;
}

Consider ptr = malloc(sizeof *ptr * n); style of using *alloc(). It is easier to code right, review and maintain than ptr = malloc(sizeof (de-referenced_ptr_type) * n);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.