Link to home
Start Free TrialLog in
Avatar of learn
learn

asked on

declare/define a two D array dynamically and destroy it afere using

It may be simple, but can you tell me how to ?
I want to use double or similar precision 2 D array.
ASKER CERTIFIED SOLUTION
Avatar of Kent Olsen
Kent Olsen
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi learn,
Check out the following code:
http://code.axter.com/allocate2darray.h
http://code.axter.com/allocate2darray.c

David Maisonave (Axter)
Cheers!
Example usage:
#include "allocate2darray.h"

double **My2D_double = ALLOCATE2DARRAY(double, x, y);

//Now to free it
Free2DArray(My2D_double);

The above method is more efficient because only two calls are made to malloc and when you free it, only two calls are made to free.
David,

Nice code! Very neat! Only problem (rare and unlikely) is that if ppi allocates but pool allocation fails you'll leak the ppi block but that's no criticism!

Paul
>>Nice code! Very neat! Only problem (rare and unlikely) is that if ppi allocates but pool allocation fails you'll leak the ppi block but that's no criticism!

Ahhhh!
Good catch.  No matter how good you *think* you are, it always helps to have an extra pair of eyes.

I just updated the code.
Thanks
Hi Axter, Paul,

I was thinking that this was too close to being a homework question for complete code.  Guess everyone didn't see it that way.  :)



Kent
>>I was thinking that this was too close to being a homework question for complete code.

Looking at the questioner's history, it doesn't look like a homework question.
90% time when it's a homework question, it's posted by a newbie, and usually it's the first question asked.

I usually give questioners that have been EE members for over 3 years, the benefit of the doubt.

This questioner has been an EE member longer than I have.....
Actually, he's been an EE member longer than all of us!!!
Hi Axter,

   :)


Kent
Avatar of learn
learn

ASKER

Hi,

Thanks a lot for all of you!

I declare that this is not a home work.

I know C before but forgot all of them. I think I should answer some questions in other languages so that you believe me.

OK, I am going to read your suggestions and links.
Hi learn! Glad to meet you!

Hi Kent! You mean:

>>Array2D = (int **) malloc (sizeof (int*) * YSize;   // Allocate the base array

Was a giveaway newbie code example? :-) The missing bracket was a dead geveaway was it? ;-)

Nah! Just kidding! Not many students get to 2D and pointers to pointers nowadays, but good point! I should have been the one to ask! :-(

HI David!

Could you post the code here please, just for completeness, now its perfect :-) Thanks!

Thanks.

Have a good weekend all!

Paul
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Excellent!

My only suggestionwould be:

         *(ppi + i) = curPtr;
 
becomes:

         ppi[i] = curPtr;

'cause I dont like faking array access but thats only a personal thing. :-)

and, of course:

    free(*Array);
     free(Array);

would be safer as:

    if (Array)
    {
     if (*Array) free(*Array);
    free(Array);
    }

you could then use:

    if (!ppi || !pool)
     {  /* Quit if either allocation failed */
        Free2DArray(ppi);

but that's just polish!
 
Paul
>>you could then use:
>>
>>    if (!ppi || !pool)
>>     {  /* Quit if either allocation failed */
>>        Free2DArray(ppi);

That's a good idea.
Avatar of learn

ASKER

I also made my own version :) and got no error!
Can you check my code:

#include <stdlib.h>

int main()
{
      int xSize=10, ySize=10, i;
      double **array2D = (double **) malloc (sizeof (double *) * ySize);
      for (i=0; i<xSize; i++)
      {
            *array2D = (double *) malloc (sizeof (double) * xSize);
      }

      for (i=0; i<xSize; i++)
      {      
      free(array2D[i]);
      }
      free (array2D);

      return 0;
}

There are 3 problems:

1. Why I cannot replace       
int xSize=10, ySize=10, i;
by
      int xSize, ySize, i;
      xSize = 10;
      ySize=10;
I need that way because I will read xSize and ySize from file or keyboard.

2. In
*array2D = (double *) malloc (sizeof (double) * xSize);
what the function malloc returns? Why we need (double *) before it?

3. Axter's code for free is simpler than mine :) Why not follow the inverse way of allocation to do free
      for (i=0; i<xSize; i++)
      {      
      free(array2D[i]);
      }
      free (array2D);

 
However, what would be the chances of ppi failing, but pool succeeding?

I'm not sure if that is possible.
>>I also made my own version :) and got no error!

Your version has to make many calls to malloc.
If you look at my code, you'll see that it only makes two calls to malloc.
In the second malloc call, it creates a single memory pool that is than distributed to the pointers.

>>what the function malloc returns? Why we need (double *) before it?
If you compile in a *.c file, you don't need to cast it, but if you compile in a *.cpp file or a C++ compiler, than you'll need the type casting, because C++ has strict type casting rules.

>>Axter's code for free is simpler than mine :) Why not follow the inverse way of allocation to do free
The reason my code is simpler, is because the allocation is simpler.
>>>>Axter's code for free is simpler than mine :) Why not follow the inverse way of allocation to do free

FYI:
Code that requires more malloc and free calls are not only less efficient, but it's also more prone to memory leaks.
In general, you want to limited malloc calls as much as possible.
Hmm... but then the code should become:

void **Allocate2DArray(int TypeSize, int x, int y)
{
     void **ppi          = malloc(x*sizeof(void*));
     if ( ppi )
     {
       if ( ppi[0] = malloc(x*y*TypeSize) )
       {
        unsigned char *curPtr = ppi[0];
        int i;
        // Could start i at 1 here but no need really.
        for(i = 0; i < x; i++)
        {
             ppi[i] = curPtr;
             curPtr += y*TypeSize;
        }
       }
       else
       {
       // Inner allocation failed.
       free(ppi);
       ppi = NULL;
       }
     }
     return ppi;
}

Isnt it strange how defensive coding always seems to force you to minimise processing time and correctly structure? This version avoids the pointless second malloc if the first fails and uses one less stack variable! We could skip the first assignment in the loop by starting 'i' at 1 but in my opinion that starts making the code messy.

Sorry to be pedantic! No criticism intended :-)

Paul
The above code will not compile on a *.c compiler, since you need to declare all the variables on the start of the function.

I'm not sure if this is specific to old C standard, or if it's part of the current C standard.
FYI:
That's one thing I really hate when using a C compiler.  I prefer just in time variable declarations.
I know a lot of old C programmers prefer to declare everything at the top, and no matter what you say to them, they will not see the benifit of declaring them close to where you first use them.

Sorry for going OT......
Avatar of learn

ASKER

Axter,

Thank you.
However,  I cannot allocate the array before I read xSize and ySize from file or keyboard.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>>However,  I cannot allocate the array before I read xSize and ySize from file or keyboard.

I'm not sure what you're trying to say here.
Are you having problems with the code using logic that pulls the size at runtime?
>>I prefer just in time variable declarations.
I totally agree! It makes pulling code out into a function so much easier and its more stable to enhancements.

Paul
>>and, of course:
>> free(*Array);
>> free(Array);
>>would be safer as:
>>if (Array)
>>{
>>if (*Array) free(*Array);
>>free(Array);
>>}

FYI:
IAW C standard, you can call free with a NULL value.
So the free function can look like this:

void Free2DArray(void ** Array)
{
     if (Array) free(*Array);
     free(Array);
}

Above code should be safe, even if NULL.
Avatar of learn

ASKER

PaulCaswell,

Thanks a lot. You are right. It works:
int xSize, ySize, i;      double **array2D;
xSize=10; ySize=10;
array2D = (double **) malloc (sizeof (double *) * ySize);
>>int xSize, ySize, i;     double **array2D;

I recommend you initialize your pointer to NULL.
double **array2D = NULL;
>>IAW C standard, you can call free with a NULL value.
Good point! I keep forgetting this! I work with about 5 different C compilers at work! I think the oldest dates back to the 70's (MS C 6.0) and would definitely cause a bang if you tried to free NULL.

Paul
Avatar of learn

ASKER

Axter,

I was doing wrong.....Now it is fine.
Good luck learn! Come back again whenever you like!

Sorry we hijacked your question with our idle chatter. We'll try to focus better next time. It IS friday night however! :-)

Paul
Avatar of learn

ASKER

Thanks a lot again for all your helps!
e 70's (MS C 6.0)

This is truly an old C compiler -- didn't know ms made C compiler in the 70s ;-)

Oops! A about a decade out! Its (C) 1984-90 but its still ancient! 128 caracter limit on the command-line! No debugger! Pretty unhelpful!

Paul
>>A about a decade out! Its (C) 1984-90 but its still ancient! 128 caracter limit on the command-line! No debugger!

I had to use this compiler about 3 years ago, and it's limitations broght back some painfull memories of programming in the 80's.
I created the following logging code just to debug the code:
http://code.axter.com/debuglog.h
http://code.axter.com/debuglog.c

This compiler support cross-compiling to OS2, and the above code was used on OS2, but I'm pretty sure it will also work for DOS.
Thanks David!

I've been working with it for 7 years now and I've got buckets of stuff I use for all sorts of things, including debug logging etc. but thanks for the thoughts.

I eventually wrote a tool that replaced CL.EXE under Visual Studio 6 so it detects which compiler I want it to use from environment variables and translates the command-line parameters into the correct form for it (and 3 other compilers I have to use) before launching it. It means I have full browse features and SourceSafe integration for all my development.

Paul
>>I eventually wrote a tool that replaced CL.EXE under Visual Studio 6.

I did the same exact thing for the project I was working on.
Makes me wonder how many times we developers reinvent the wheel...??? :-)