BUG: __Huge New Operator Fails with Variable Size

Last reviewed: July 22, 1997
Article ID: Q111754
1.00 1.50 WINDOWS kbtool kbbuglist

The information in this article applies to:

  • The Microsoft C/C++ Compiler (CL.EXE) included with:

        - Microsoft Visual C++ for Windows, versions 1.0 and 1.5
    

SYMPTOMS

If a variable is used as the size parameter to the __huge new operator, the return value will be NULL or a pointer to a memory block that is smaller than requested.

CAUSE

The problem is that only the lower order word of the variable that is passed as the length parameter will be used. Therefore, if the allocation is less than 64K, the call will be successful. However, if the allocation size is greater than 64K, the call to new will fail as follows:

  • If the lower order word is 0 (zero), the call to new will return NULL.
  • If the lower order word is nonzero, then the call will return a valid pointer but the block of memory allocated will be smaller than requested.

RESOLUTION

If the variable size is constant (that is, it never changes), then substitute the absolute value as the parameter to the call to new. For example, change the following

   long lSize=0x20000;
   char __huge *pChar = new __huge char[lSize];

to the following:

   char __huge *pChar = new __huge char[0x20000];

A call to _halloc can be used instead. For example, change the following

   /* lSize==0x20000 */
   char __huge *pChar = new __huge char[lSize];

to the following:

   char __huge *pChar = (char __huge *) _halloc(lSize,sizeof(char));

NOTE: If using _halloc. be sure to use _hfree instead of delete. Also, you need to include <malloc.h>.

STATUS

Microsoft has confirmed this to be a problem in Microsoft C/C++ for MS-DOS, versions 8.0 and 8.0c. We are researching this problem and will post new information here in the Microsoft Knowledge Base as it becomes available.

MORE INFORMATION

The problem can be seen by generating an assembly listing of the code. Included below is a section of code and the accompanying assembly listing generated by using the /Fc compiler switch:

Sample Code

/*
/ Compile options needed: /Fc
*/

#include <iostream.h>

void main(void)
{
 long test=0x20000;
 char __huge * ptr;

 ptr=new __huge char[test];

// ; Line 10
//    *** 000015  b8 01 00        mov ax,OFFSET 1
//    *** 000018  50          push    ax
//    *** 000019  8b 46 f6        mov ax,WORD PTR -10[bp]
//    *** 00001c  8b 56 f8        mov dx,WORD PTR -8[bp]
//    *** 00001f  ba 00 00        mov dx,OFFSET 0
//    *** 000022  52          push    dx
//    *** 000023  50          push    ax
//    *** 000024  e8 00 00        call    ??2@YAPIXKI@Z
//    *** 000027  83 c4 06        add sp,OFFSET 6
//    *** 00002a  89 46 fa        mov WORD PTR -6[bp],ax
//    *** 00002d  89 56 fc        mov WORD PTR -4[bp],dx
//;


 if (ptr!=NULL)
  cout << "Success!";
 else
  cout << "Failure!";
}

This line is the cause of the problem:

//    *** 00001f  ba 00 00        mov dx,OFFSET 0

This destroys the upper word of the length and effectively limits you to allocating only up to 64K.


Additional reference words: 1.00 1.50 8.00 8.00c halloc free
KBCategory: kbtool kbbuglist
KBSubcategory: CLIss
Keywords : kb16bitonly


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: July 22, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.