[comp.sys.mac.programmer] Using Malloc to create variables. help?

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

  All right guys, another question and this time i'll give you the whole thing,
like a function...  Here it is.
I
extern int				**track;
extern int				**map;
extern char			*bigmap;
 
 
 
function()
{
 
	int	x,y;
 
 
if ( (track = (int **)( malloc( (100 * 100) * sizeof(int) + 1) )) == NULL)
		ExitToShell();
	if ( (map = (int **)( malloc( (100 * 100) * sizeof(int) + 1 ) )) == NULL)
		ExitToShell();
	if ( (bigmap = (char *)( malloc( (100 * 100 * 32) * sizeof(char) + 1 ) )) == NULL)
		ExitToShell();
		
for (x = 0;x < 100; x++)
	for(y =0; y < 100; y++)
	{
		map[x][y] = -1;
		track[x][y] = -1;
	}
}}

there you go.  Now the problem is that when the for loops go to initialize the 
variables, it crashes with various error codes in the debugger.  Any hints,
did I declare track, map, and bigmap correctly.
  Bigmap is eventiually going to be a 100 by 100 array of icons, (the map
of my game).  Also ignore the 32 size, i'll be changing that to 128 on my
side.  Thanks.  the malloc do I need to dereference the map and track variables
before I even attempt use them?
  I.e. like (*map)[x][y] and (*track)[x][y]?  wouldn't that be the same as
defining a pointer like this
 int *pointer = ***map;
This pointer stuff is really getting wild...
  Thanks..

*******************************************************************************
*  Kevin Hill
*  San Diego State University, Accounting Major.
*  No matter where you go, there you are.
*******************************************************************************
*               \
*         *=====+)---------------------------
*               / 
*  San Diego State Fencing
*******************************************************************************

heksterb@Apple.COM (Ben Hekster) (01/18/91)

You write:

extern int	**map;
 
if ( (map = (int **)( malloc( (100 * 100) * sizeof(int) + 1 ) )) == NULL)
	ExitToShell();

	map[x][y] = -1;

Well, for one thing, malloc returns pointers to nonrelocatable blocks, not
handles.  Since arrays and pointer types are equivalent in C, the compiler
interprets `map' as an array of pointers to arrays of int.  Although the
variables are declared incorrectly, the access `map[x][y] = -1' is correct.
My guess is that the compiler you use employs 2-byte ints, and since pointers
are 4 bytes in the Macintosh world, the array accesses are therefore writing
twice as much stuff into memory as you expect (0xffffffff rather than 0xffff)
so you end up stepping all over the Memory Manager data structures.

	You can go two ways--either stick with C's malloc-type allocation, or
use the Memory Manager NewHandle calls.  Obviously the Memory Manager stuff
is a little friendlier since it gives the system a chance to juggle memory
when it gets tight.

	By the way, what is the `+ 1' for in your malloc?  Paranoia??  If so,
I'd suggest taking it out because otherwise it's a great way of hiding bugs
in your algorithms.  You *do* want to find bugs, don't you?

	If you haven't got it yet, I strongly recommend buying Kernighan &
Ritchie's "The C Programming Language".  An excellent book that will teach
you everything you need to know and renders everything else obsolete.

_______________________________________________________________________________
Ben Hekster                           | "I've had my fun
Student intern                        |  but now it's time
AppleLink:   heksterb                 |  to serve your conscience
Internet:    heksterb@apple.com       |  overseas"
BITNET:      heksterb@henut5          | --Orange Crush, R.E.M. (Green)

phils@chaos.cs.brandeis.edu (Phil Shapiro) (01/18/91)

In article <6996@crash.cts.com> kevin@crash.cts.com (Kevin Hill) writes:
   [ ... code deleted ... ]
   if ( (bigmap = (char *)( malloc( (100 * 100 * 32) *
        sizeof(char) + 1 ) )) == NULL)

I missed the original posting, so forgive me if I missed something
essential.  The above line won't work, since 100 * 100 * 32 won't fit
into a 16 bit integer value.  If you use, say 100L, then this
expression will work OK.  Also, make sure you're including <stdlib.h>.

	-phil

--
   Phil Shapiro                           Technical Support Analyst
   Language Products Group                     Symantec Corporation
		Internet: phils@chaos.cs.brandeis.edu
-- 
   Phil Shapiro                           Technical Support Analyst
   Language Products Group                     Symantec Corporation
		Internet: phils@chaos.cs.brandeis.edu

hairston@henry.ece.cmu.edu (David Hairston) (01/18/91)

[kevin@crash.cts.com (Kevin Hill) writes:]
[] All right guys, another question and this time i'll give you the whole
[] thing, like a function...  Here it is.

extern int				**track;
extern int				**map;
extern char			*bigmap;
 
 
 
function()
{
 
	int	x,y;
 
 
if ( (track = (int **)( malloc( (100 * 100) * sizeof(int) + 1) )) == NULL)
		ExitToShell();
	if ( (map = (int **)( malloc( (100 * 100) * sizeof(int) + 1 ) )) == NULL)
		ExitToShell();
	if ( (bigmap = (char *)( malloc( (100 * 100 * 32) * sizeof(char) + 1 ) )) == NULL)
		ExitToShell();
		
for (x = 0;x < 100; x++)
	for(y =0; y < 100; y++)
	{
		map[x][y] = -1;
		track[x][y] = -1;
	}
}}

[] there you go.  Now the problem is that when the for loops go to
[] initialize the variables, it crashes with various error codes in the
[] debugger.  Any hints, did I declare track, map, and bigmap correctly.
[] Bigmap is eventiually going to be a 100 by 100 array of icons, (the map
[] of my game).  Also ignore the 32 size, i'll be changing that to 128 on my
[] side.  Thanks.  the malloc do I need to dereference the map and track
[] variables before I even attempt use them?

umm, i'll keep an eye out for this game ... ;)

i'd like to see the monitors that can support arrays of 100x100 icons
(note that a 640x480 screen can only support 20x15 side by side icons).

you've made numerous errors in your example which prompts me to suggest
that you get a copy a Kernighan & Ritchie, "The C Programming Language",
2nd Edition and digest it (slowly).  also, if you're using Think C, try
to leaf thru the various header files and do the tutorial projects, etc.
getting your hands on as much example source code as you can would also
help.

some things you should know:

malloc will return a _pointer_ to some memory block (properly aligned)
of the size you specify (you should be precise in defining the space).
it is best to allocate this type of space very early in your program
as they are _non-relocatable_ blocks and so may cause problems with
memory management (fragmentation) if allocated later.  alternatively,
i'd suggest you get Inside Macintosh I-V and read up on the mac's
memory management.

consider this 1-D array:
fooType a[numElems];

`a' is a pointer to the beginning of this data structure and so the
following are equivalent: a[i] == *(a + i).  a[i] is the ith element
of a, whereas *(a + i) dereferences the address which is at an
offset of (i * sizeof(fooType)) from the address `a' (i.e. the
ith element of `a').  note that the compiler can handle this address
math given the declaration of an array of elements of type fooType.

consider this 2-D array:
grokType b[rowDim][colDim];

here each b[n] is a pointer to an array of colDim elements of type
grokType (still with me?).  clearly each b[n] is like the `a' of
the previous example.  `b' is a pointer to the beginning of this
array of pointers.  given the declaration above, the memory would
be contiguous however for functionality this need not be the case.
the array of pointers would need to be self-contiguous and could
point to disjoint (but self-contiguous) arrays of type grokType.
this is what you should expect from malloc.  getting back to
address math, b[n] is the nth pointer (offset n from b) out of rowDim
such pointers to an array of colDim elements of type grokType (whew!).

although i don't think this is what you want for your program (i.e.
i think you can simply define some Rect's and place your icons
in those Rects and whatever ...) it may be instructive to see some
code.

consider this _dummy_ program which does nothing useful ...

/* umm, include appropriate headers and load appropriate libraries */

#define szofIcon	128	/* 128 bytes = 1024 B&W pixels */
#define numRows		15	/* 480 / 32 = 15 */
#define numCols		20	/* 640 / 32 = 20 */

/* define a type to make things easier (i hope) */
typedef char Icon[szofIcon];	/* an Icon is an array of 128 char's */

int j,k;
Icon *bigmap[numRows];		/* allocate numRows pointers to Icons */

main()
{
    for (j = 0; j < numRows; ++j)
        /* each bigmap[n] points to an array of Icons */
        bigmap[j] = (Icon *) malloc(numCols * sizeof(Icon));

    for (j = 0; j < numRows; ++j)
        for (k = 0; k < numCols; ++k)
            /* check the equivalence of address math,
             * note that bigmap is effectively a 2-D array
             * but don't think that it is contiguous!
             */
            if ( bigmap[j][k] != *(*(bigmap + j) + k) )
                SysBeep(1);
}

btw, you should hear nothing! and you should probably check your
mallocs before using them (you don't want to dereference address 0)
and other things too numerous to mention ... ;) ...

well, i hope this helped some ...

  -dave-  
hairston@henry.ece.cmu.edu