ajayshah@alhena.usc.edu (Ajay Shah) (04/28/91)
I think I have identified a bug in TC 2.0. My machine has 645k of free memory. I bring up the TC environment (not using tcc here). I've set the memory model to be Huge. I run this program: --------------------------------------------------------------------------- 1 #include <stdio.h> 2 #include <malloc.h> 3 void 4 main() 5 { 6 int i; 7 char *ptr; 8 ptr = (char *)malloc((unsigned) 0); 9 for (i=1;i<=1024;i+=i){ 10 ptr = (char *)realloc(ptr,(unsigned)i*1024); 11 if (ptr == (char *)NULL) printf("realloc bombed when "); 12 printf("%d Kbytes realloced\n",i); 13 } 14 } 15 --------------------------------------------------------------------------- I get this output: --------------------------------------------------------------------------- 1 Kbytes realloced 2 Kbytes realloced 4 Kbytes realloced 8 Kbytes realloced 16 Kbytes realloced 32 Kbytes realloced realloc bombed when 64 Kbytes realloced realloc bombed when 128 Kbytes realloced realloc bombed when 256 Kbytes realloced realloc bombed when 512 Kbytes realloced realloc bombed when 1024 Kbytes realloced --------------------------------------------------------------------------- Question: why does he have problems allocating > 64k??? Is the culprit Intel or Borland? Now watch. Instead of taking RAM in steps of 1024 bytes, I use steps of 1000 bytes. Ie., I change line 10 to be ptr = (char *)realloc(ptr,(unsigned)i*1000); Now it works!! It goes ahead and reallocs me 1Meg without complaining! There's no way I can have this kind of free RAM on a 8086!! -- _______________________________________________________________________________ Ajay Shah, (213)734-3930, ajayshah@usc.edu The more things change, the more they stay insane. _______________________________________________________________________________
grimlok@hubcap.clemson.edu (Mike Percy) (04/28/91)
ajayshah@alhena.usc.edu (Ajay Shah) writes: >I think I have identified a bug in TC 2.0. How I wish I had a buck for each time someone says that so casually and was dead wrong. Just a few weeks ago, I had to write a scathing letter to the editors of CUJ for allowing such statements to be made without a shred of evidence -- in fact all could have been easily dis-proven with a simple trip to the manuals. >My machine has 645k of free memory. I bring up the TC environment >(not using tcc here). I've set the memory model to be Huge. >I run this program: >--------------------------------------------------------------------------- >1 #include <stdio.h> >2 #include <malloc.h> >3 void >4 main() >5 { >6 int i; >7 char *ptr; >8 ptr = (char *)malloc((unsigned) 0); >9 for (i=1;i<=1024;i+=i){ >10 ptr = (char *)realloc(ptr,(unsigned)i*1024); >11 if (ptr == (char *)NULL) printf("realloc bombed when "); >12 printf("%d Kbytes realloced\n",i); >13 } >14 } >15 >--------------------------------------------------------------------------- >I get this output: >--------------------------------------------------------------------------- >1 Kbytes realloced >2 Kbytes realloced >4 Kbytes realloced >8 Kbytes realloced >16 Kbytes realloced >32 Kbytes realloced >realloc bombed when 64 Kbytes realloced >realloc bombed when 128 Kbytes realloced >realloc bombed when 256 Kbytes realloced >realloc bombed when 512 Kbytes realloced >realloc bombed when 1024 Kbytes realloced >--------------------------------------------------------------------------- >Question: why does he have problems allocating > 64k??? Is the >culprit Intel or Borland? >Now watch. Instead of taking RAM in steps of 1024 bytes, I use >steps of 1000 bytes. Ie., I change line 10 to be >ptr = (char *)realloc(ptr,(unsigned)i*1000); >Now it works!! It goes ahead and reallocs me 1Meg without complaining! >There's no way I can have this kind of free RAM on a 8086!! When are people going to learn how to read a manual for crissakes?????? Let's go through this one more time, slowly. But first, Ajay, no offense to you personally. There must be about 50 or so postings montly which ask virtually the exact same question. The first point of order is to open a manual (or check out the prototypes for *alloc in malloc.h). Notice that the *alloc functions take a parameter of type size_t. Now, everyone should realize that size_t represents the upper limits of allocation amounts. In TC, size_t is typedef'd thusly: typedef unsigned int size_t; The largest value allowable in an unsigned int (in TC) is 65535 (64K), therefore the largest block of memory which can be *alloc()'d is 64K. This turns out not to be the case. Depending on the memory model in use, each *alloc()'d block uses either 8 or 16 bytes of header information. There is also some space in a 64K byte block which cannot be used because *alloc() functions work in 8-byte chunks. The real upper limit of *alloc() is closer to 655310 useable bytes. This 64K limit has to to with the limits of the segmented Intel architecture and efficiency. Borland provides a way around this with the non-standard pointer type huge, and the far*alloc functions. The far*alloc functions take a long int as a size request.i Huge pointers are a significant CPU user, and aren't recommended unless you absolutely must have >64K structures. As for the program not working with 1024, but working fine with 1000, consider what the standard conversions being done here. 1024 is of type int, multiplied by an unsinged int. The rules say that if either operand is of type unsigned, the other is converted to unsigned. So now we have <unsigned int, 64> * <unsigned int, 1024>, which is 65536. But 65536 cannot be represented as an unsigned int, so the compiler forces it in by truncating any high order bits. The result is, according to this, now 0! Of course realloc() returns NULL if you ask it to resize a size 0. Notice that the rest of your numbers truncate to exactly 0, so they all fail -- not because you don't have the memory or anything like that. They fail because of the _definition_ of realloc()! Changing 1024 to 1000 changes this a bit, but you are a far cry from allocating 1 meg. 1 * 1000 = 1000, fits in unsigned int -- no problem 2 * 1000 = 2000, fits in unsigned int -- no problem 4 * 1000 = 4000, fits in unsigned int -- no problem 8 * 1000 = 8000, fits in unsigned int -- no problem 16 * 1000 = 16000, fits in unsigned int -- no problem 32 * 1000 = 32000, fits in unsigned int -- no problem 64 * 1000 = 64000, fits in unsigned int! -- realloc() works ok 128 * 1000 = 128000, problem, must truncate, realloc() gives 62465 byte chunk 256 * 1000 = 256000, after truncation, realloc() gives 59392 block 512 * 1000 = 512000, after truncation, we get a 53248 byte chunk from realloc() 1024 * 1000 = 1024000, we ask realloc() for a 40960 byte block So, you can see that we never allocated >64K in one call. Nor is this a bug of any sort. It is simply a phenomena of compiler limits, which are documented quite reasonably. I suppose Borland could come out and explicitly state in the docs exactly what the biggest size block which can be allocated by *alloc(), but maybe they feel that they already did that in the prototype description. C is not a language for those unconcerned with "trivial" details like compiler-based limitations, nor for those who cannot be bothered to spend a little time with a manual to determine what these limits are. Hell, browse through stddefs.h, stdlib.h, and limits.h at least once to see how things look! "I don't know about your brain, but mine is really...bossy." Mike Percy grimlok@hubcap.clemson.edu ISD, Clemson University mspercy@clemson.BITNET (803)656-3780 mspercy@clemson.clemson.edu
aduncan@rhea.trl.oz (Allan Duncan) (04/30/91)
From article <32383@usc>, by ajayshah@alhena.usc.edu (Ajay Shah): > I think I have identified a bug in TC 2.0. [sample program and output deleted] > Question: why does he have problems allocating > 64k??? Is the > culprit Intel or Borland? Just Intel and the program - because of Intel's abysmal addressing scheme with its unconnected segment and paragraph registers (I think that's the terminology) it is difficult to handle addressing in lumps bigger than 64K. Borland has chosen to go for speed and compactness by limiting you to a 16 bit int (+/-32K, or 64K unsigned), probably in part because of this. On the 68000 CPU there are compilers that will do either 16 or 32 bit ints at the flick of a compiler switch. Allan Duncan ACSnet a.duncan@trl.oz (+613) 541 6708 Internet a.duncan@trl.oz.au UUCP {uunet,hplabs,ukc}!munnari!trl.oz.au!a.duncan Telecom Research Labs, PO Box 249, Clayton, Victoria, 3168, Australia.