Solved

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

Posted on 2006-03-24
747 Views
It may be simple, but can you tell me how to ?
I want to use double or similar precision 2 D array.
0
Question by:learn

LVL 45

Accepted Solution

Hi learn,

int **Array2D;
int XSize = 10;   // Width of the array
int YSize;= 100; // Length of the array;
int idx;

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

// Now loop through the array assigning memory for each row of the array.  (malloc size is sizeof (int) * XSize).

To Destroy the array, free() each of the rows then the base array.

Good Luck!
Kent
0

LVL 30

Expert Comment

Hi learn,
Check out the following code:
http://code.axter.com/allocate2darray.h
http://code.axter.com/allocate2darray.c

David Maisonave (Axter)
Cheers!
0

LVL 30

Expert Comment

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.
0

LVL 16

Expert Comment

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
0

LVL 30

Expert Comment

>>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
0

LVL 45

Expert Comment

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
0

LVL 30

Expert Comment

>>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.....
0

LVL 30

Expert Comment

Actually, he's been an EE member longer than all of us!!!
0

LVL 45

Expert Comment

Hi Axter,

:)

Kent
0

Author Comment

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.

0

LVL 16

Expert Comment

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
0

LVL 30

Assisted Solution

Sure.

/* allocate2darray.h */

#define ALLOCATE2DARRAY(Type, x, y) (Type**)Allocate2DArray(sizeof(Type), x, y)

void **Allocate2DArray(int TypeSize, int x, int y);
void Free2DArray(void ** Array);

/* allocate2darray.c */
#include <stdlib.h>

void **Allocate2DArray(int TypeSize, int x, int y)
{
void **ppi            = malloc(x*sizeof(void*));
void *pool            = malloc(x*y*TypeSize);
unsigned char *curPtr = pool;
int i;
if (!ppi || !pool)
{  /* Quit if either allocation failed */
if (ppi) free(ppi);
if (pool) free(pool);
return NULL;
}

for(i = 0; i < x; i++)
{
*(ppi + i) = curPtr;
curPtr += y*TypeSize;
}
return ppi;
}

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

LVL 16

Expert Comment

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
0

LVL 30

Expert Comment

>>you could then use:
>>
>>    if (!ppi || !pool)
>>     {  /* Quit if either allocation failed */
>>        Free2DArray(ppi);

That's a good idea.
0

Author Comment

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);

0

LVL 30

Expert Comment

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

I'm not sure if that is possible.
0

LVL 30

Expert Comment

>>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.
0

LVL 30

Expert Comment

>>>>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.
0

LVL 16

Expert Comment

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
0

LVL 30

Expert Comment

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.
0

LVL 30

Expert Comment

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......
0

Author Comment

Axter,

Thank you.
However,  I cannot allocate the array before I read xSize and ySize from file or keyboard.
0

LVL 16

Assisted Solution

>>However, what would be the chances of ppi failing, but pool succeeding?
None! But ppi could succeed while pool then failed couldnt it? pool is likely to be significantly larger.

>>1. Why I cannot replace
...
Because you then go on to declare double** Array2D which you cant do in C without a { before it. Add a { before the Array allocation and it should work, but better still, make the array allocation a separate function and the problem solves itself.

The essential difference between yours and David's is that you allocate each column separately while Davids allocates one block of data for the whole content of the array and then parcels it out by pointing the index into parts of it. There are some minor downsides to this but overall its quicker and more efficient.

The minor downside with David's method is that if you accidentally walk off the end of one column you only corrupt the start of the next. - With yours, this could be caught by some debuggers automatically because you would be writing to free memory which can be detectable.

Paul
0

LVL 30

Expert Comment

>>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?
0

LVL 16

Expert Comment

>>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
0

LVL 30

Expert Comment

>>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.
0

Author Comment

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);
0

LVL 30

Expert Comment

>>int xSize, ySize, i;     double **array2D;

I recommend you initialize your pointer to NULL.
double **array2D = NULL;
0

LVL 16

Expert Comment

>>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
0

Author Comment

Axter,

I was doing wrong.....Now it is fine.
0

LVL 16

Expert Comment

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
0

Author Comment

Thanks a lot again for all your helps!
0

LVL 3

Expert Comment

e 70's (MS C 6.0)

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

0

LVL 16

Expert Comment

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
0

LVL 30

Expert Comment

>>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.
0

LVL 16

Expert Comment

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
0

LVL 30

Expert Comment

>>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...??? :-)
0

LVL 16

Expert Comment

0

## Featured Post

This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn hoâ€¦
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to useâ€¦
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use conditional statements in the C programming language.