[comp.lang.c] Memory Allocation Problem

kevin@crash.cts.com (Kevin Hill) (01/23/91)

  I am still having problems with the malloc use in allocating memory
for a two dimensional array.  I thank everyone that has been attempting
to help me with this.
  As of now, 
 these are the variables outside of the function to follow:

int	**track;
int	**map;
char	*bigmap;

int					cursor,x1 = 0,y1 = 0,gx,gy;
WindowPtr				thewind,thewind1;
WindowRecord			windowmemory,windowmemory1;
BitMap				themap1,store;
char					iconmap[128];
Rect					oldbox;
int					**track;
int					**map;
char					*bigmap;
 
Initialize()
{
	int	x,y;
	
	gx = gy = 0;
	
	
	store.rowBytes = 4;
	SetRect(&store.bounds,0,0,32,32);
	
	if ( (bigmap = (char *)( malloc( (unsigned)(100 * 100 * 128)) )) == NULL)
		ExitToShell();
	track = (int **)malloc( (unsigned)(100 * sizeof(int *)) );	
	
	track[0] = (int *)malloc( (unsigned)( 100 * 100 * sizeof(int)) );
	if (track[0] == NULL)
		ExitToShell();
		
	map = (int **)malloc( (unsigned)(100 * sizeof(int *)) );
	
	map[0] = (int *)malloc( (unsigned)(100 * 100 * sizeof(int)) );
	if (map[0] == NULL)
		ExitToShell();
	
	
	for (x = 1; x < 100; x++)
	{
		track[x] = track[x-1] + (100 * sizeof(int));
		map[x] = map[x-1] + (100 * sizeof(int));
		for (y = 0; y < 100; y++)
		{
			map[x][y] = -1;
			track[x][y] = -1;
		}
	}
}
}

So that is the extent of the stuff that I have attempted.  Now the problem is 
that when the computer allocates using malloc, it returns very low address'
or very high address'.  The low ones, which are the most common are standard,
and they are 0x000012A, is that an address to a master pointer list, and I need
to dereference that also?  Also, when I complete the malloc to issue the 
100 pointers for either of them, if I use the debugger to find the address 
of track[0], track[1], it is still low.  Is malloc buggy, or am I.  I am betting
that I am the one that is buggy!  Also, yes I did read the FAW sheet that 
Steve Summit sent me, (FAQ not FAW, sorry) and question #20 is the only one
that applies to my question, and if you look at the code above, you will
see that I did follow it, and I think that I understand it.
  For example, when track is allocated by the malloc statement, I am giving
memory space for the pointers that will point to the integers that I am trying
to store.  Then after that, I put into track[0] the beginning of the space
of the actual 100x100 space for the integers of the two dimensional array.
The for loop below sets up the pointers to point to the correct places in
memory, and initializes the values of the pointers.
  So, far, the machine crashes at the malloc points, sometimes.  Or always, when
it gets to the actual initialization of the array.  Yes, I know that if I have
the wrong address' I am overwriting areas that the system could be using, but
malloc should be sending back to me the correct address' and I believe that
I am using the right coding to create the two-dimensional arrays that I am using.
Thanks.
  

jdb@reef.cis.ufl.edu (Brian K. W. Hook) (01/23/91)

In article <7156@crash.cts.com> kevin@crash.cts.com (Kevin Hill) writes:
>
>  I am still having problems with the malloc use in allocating memory
>for a two dimensional array.  I thank everyone that has been attempting
>to help me with this.

I don't know exactly what system you are writing on, but I assume that it
is PC compatible.  Actually, some code looks like Mac, but either way it
is not very relevant.

Have you tried using a SINGLE pointer instead of two?  Or are you doing
something that I am not aware of.  For example, I wrote a windowing 
library that looks much like some of that code you are using (which actually
looks quite a lot like the MetaWINDOWS library).

typedef struct _window {
	int   width, height;
	BYTE *oldImage;
        ...
} WINDOW;

While it is more intuitive to declare an array of pointers for a rectangular
region I have found that the following works REAL well and adds some 
simplicity.

void createWin ( WINDOW *wnd /* Whatever else needs to be passed */ )
{
   ...
   wnd->oldImage=(BYTE *)(malloc(wnd->width*wnd->height)+1);  // I add 1
							      // just in case
   ...
}

This assumes that the WINDOW doesn't cast a shadow and that the area behind is
definable as a BYTE (8 bits, as far as I am concerned...a 256 color bit map)
for each discreate location behind the WINDOW (i.e. pixel).

Now, back to the two dimensional array.  How about indicing each pointer 
that you need using a little bit of pointer arithmetic.  The equation
should be:

BYTE *rowToFind=wnd->oldImage+(wnd->width*row+column);

This assumes that "row" and "column" is the starting pixel for the address you
wish to find.  Since you are looking for a pointer per row (thus simulating
a two dimensional array) "column" would be 0.  Then you would just grab
wnd->width amount of BYTEs to get that entire line.

Hope this helped,

Brian

smbrush@helios.lerc.nasa.gov (Andrew Brush (Sverdrup)) (01/29/91)

In response to Kevin Hill's question in 7156@crash.cts.com,

I compiled and ran the following small program on my PC using MSC5.1
and on VMS using VAX C v3.0 with no problems.

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

void main(void);

void main(void){
int **track;
int ix, iy;
track = (int **)malloc( (unsigned)(100*sizeof(int *)));
track[0] = (int *)malloc( (unsigned)(100*sizeof(int)));

for (ix=1;ix<100;ix++){
    track[ix] = track[ix-1] + (100*sizeof(int));
    printf("%p\n",track[ix]);
    }
for (ix=0;ix<100;ix++){
    for (iy=0;iy<100;iy++){
        track[ix][iy] = ix*iy;
        printf("%d\n",track[ix][iy]);
        }
    }
}


This is slightly different from his program fragment:

int	**track;
int	**map;
char	*bigmap;

int					cursor,x1 = 0,y1 = 0,gx,gy;
WindowPtr				thewind,thewind1;
WindowRecord			windowmemory,windowmemory1;
BitMap				themap1,store;
char					iconmap[128];
Rect					oldbox;
int					**track;
int					**map;
char					*bigmap;

Initialize()
{
	int	x,y;
	
	gx = gy = 0;
	
	
	store.rowBytes = 4;
	SetRect(&store.bounds,0,0,32,32);
	
	if ( (bigmap = (char *)( malloc( (unsigned)(100 * 100 * 128)) )) == NULL)
		ExitToShell();
	track = (int **)malloc( (unsigned)(100 * sizeof(int *)) );	
	
	track[0] = (int *)malloc( (unsigned)( 100 * 100 * sizeof(int)) );
	if (track[0] == NULL)
		ExitToShell();
		
	map = (int **)malloc( (unsigned)(100 * sizeof(int *)) );
	
	map[0] = (int *)malloc( (unsigned)(100 * 100 * sizeof(int)) );
	if (map[0] == NULL)
		ExitToShell();
	
	
	for (x = 1; x < 100; x++)
	{
		track[x] = track[x-1] + (100 * sizeof(int));
		map[x] = map[x-1] + (100 * sizeof(int));
		for (y = 0; y < 100; y++)
		{
			map[x][y] = -1;
			track[x][y] = -1;
		}
	}
}
}


1) For some reason, he shows declarations for his pointer variables
twice.

2) His attempt to initialize track and map while also organizing their
memory results in failure to initialize row [0] of them.

3) I'm not using any error checking on malloc, although i should. 
Kevin isn't using error checking when allocating memory for track or
map.  Possibly, the request for 1,280,000 bytes (or more, depending on
sizeof(char) ) for bigmap uses up his available memory, resulting in
track==NULL (which is untested), so an attempt to do: track[0]= ....
is an attempt to assign a value to something with the address of NULL.


Andy Brush [Sverdrup Technology] 216-826-6770
SMBRUSH@MARS.lerc.nasa.gov