Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!csc.ti.com!ti-csl!tilde.csc.ti.com!axis!logic.dsg.ti.com!bruce From: bruce@logic.dsg.ti.com (Bruce Florman (BFLM)) Newsgroups: comp.sys.mac.programmer Subject: Re: malloc() Help Message-ID: <1991Feb8.163533.9724@axis.dsg.ti.com> Date: 8 Feb 91 16:35:33 GMT References: <15828@milton.u.washington.edu> Sender: news@axis.dsg.ti.com (System News Administ) Organization: Texas Instruments, Austin, Tx. Lines: 76 In some previous article, someone writes: >>For some reason, I have trouble using malloc() in THINK C. >>Here is an example: >>doit(num) >>int num; >>{ >> char *back; >> >> back=malloc(num); >>} >>If you know what is wrong with the code PLEASE E-mail me and tell me what >>I need to fix. Thank you. In article rg2c+@andrew.cmu.edu replys: > >Your call to malloc() can't work because the syntax is wrong. You have to >specify the type of pointer you wish to create. Example. > > back = (char *) malloc (num); > >If you want to malloc() memory for a structure, you'd use the sizeof() function >Example: > > back = (struct_name *) malloc (sizeof (struct_name)); Since I (and others I'm sure) had just answered this same question via email a few days earlier, I chose to let someone else handle this one. But since the first posted reply isn't correct, I'll answer one more time. Unlike many C compilers, Think C implements 16-bit ints instead of 32-bit ints. Compiler writers are allowed to do this because K&R and ANSI state only that int is the "natural size of integers on the host machine." Since the MC68000 has a 16-bit data bus, so 16 bits may be moved more quickly than 32 bits, and since the Macintosh ROM was written to use Lisa Pascal's 16-bit Integer type, the writer(s) of the Think compiler chose 16 bits as the size of int. The writers of the MPW C compiler (and the Aztec compiler and the compilers available on most 680x0 based Unix boxes) chose to implement 32-bit ints because the MC68020 and beyond all have 32-bit data busses, and because it avoids the problems encountered by sloppy programmers who assume that sizeof(int) == sizeof(char *). :-) The malloc call fails because malloc hasn't been prototyped. Without a declaration, the compiler assumes that malloc is a function returning int. Dispite the fact that malloc generates a full 32-bit pointer value, the compiler only knows to take 16 bits of it, so upper half of the address is stripped off. Then, since the int is being assigned to a pointer variable, the 16-bit value is being sign-extended into 32 bits. This process usually (but not always) results is a completely nonsensical pointer value. The cast suggested by the first respondent doesn't change this at all, since it simply tells the compiler to convert an int into a pointer, which is what it was going to do anyway. The malloc call in the above example fails at another point as well. The malloc function expects an argument of type size_t, but an int is being passed. Without a prototype, the compiler doesn't know to coerce the 16-bit argument into 32 bits, so while only two bytes are being pushed onto the stack, the malloc function itself is looking at a four byte argument. Since the upper two bytes of this argument are what was passed, and the lower two bytes are something else entirely, malloc thinks that a HUGE block is being requested (at least 65,536 times larger than what was intended). Unless num was a very small number, the request probably can't be satisfied, so malloc will return NULL in this case. Even if malloc had been declared with an "extern char *malloc();" declaration, without a prototype, and without a cast like "(size_t)num", the malloc call will fail. The bottom line of all this is that you should ALWAYS "#include " in any file which uses malloc and its kin. Now a note to Rich Siegal and the other folks at Symantec: Since this question arises on an almost weekly basis, why don't you folks include a caveat IN BIG BOLD LETTERS on the malloc page of the _Standard Libraries Reference_ which explains this common pratfall? It would make the lives of your new customers a little easier and spare the net some bandwidth. --Bruce Florman