[comp.lang.c++] How to fread a long data stream?, Turbo C++ "features"

quimby@itsgw.rpi.edu (Tom Stewart) (12/11/90)

zielinski@acfcluster.nyu.edu writes:
>
>Problem: Using Turbo C++, getting fread to read a large number of 
>data points (160,000 short integers). The following structure 
>worked in (Microsoft) C, but fails in Turbo C++. It will only 
>read 28,928 two-byte data; this corresponds to the remainder of 
>160000/65536. 
>
>  long NumPts=160000L;
>  long NumRead;
>  static short huge x[160000L];
>  printf("Array size is %ld\n",(long)sizeof(x));    /* OK up to here */
>  Numread=fread(x,sizeof(short),NumPts,file1);  /* only reads 28,928 */
>

"..even though the huge model permits static data to total more than 
 64k, it still must be less than 64K in each module"
                  p. 199, Turbo C++ Programmer's Guide

If you enable stack checking (default is not), the above program segment 
will terminate with a stack overflow.  The solution to this problem would
seem to be:
  
    short huge *x;
    x = new x[160000l];		// this does not work in Turbo C++

The problem with this is that 'new' calculates the size as a 16 bit
value in the AX register, pushes this on the stack, and calls    
'operatornew' to allocate the memory, which in turn calls 'malloc'.
There is no way to allocate more than 64k at a time with 'new'.  
(A call to Borland's tech support verified this as well.)
  
The fix is to use farmalloc instead:
  
    x = (char huge *) farmalloc(16000l);      // this works ok
  
Be sure to cast to long before multiplying the farmalloc parameter.

The nasty bit of all this is that the allocations return valid
pointers, not NULL, and the pointers point to areas much smaller
than requested, AND that the array indexes, if used, don't wrap
around the allocated block, if they wrap at all.
  
When using new, then, the programmer either has to verify that
the size is <64k before the allocation, or check to see if the size
of the allocated block is large enough after allocation.  A way to
check the alloc in the huge model is:

    unsigned huge *dummy;
    unsigned size;

    /* please note that not only is this a kludge, it is a 
       non-portable, undocumented kludge.  It is, however,
       usefull for debugging  (MS-DOS 3.30) */

    dummy = (unsigned huge*) x;
    dummy = dummy - 2;  // MS-DOS allocated memory has a 4 byte header
    size = *dummy;  // size is the number of paragraphs, including the
                    // header
    // (1 paragraph == 16 bytes)

Is there any clean way around this mess?

Quimby
  
(replies to:  quimby@mts.rpi.edu, quimby@rpitsmts.bitnet)