BUG: Custom-Based new() and delete() Fail

ID: Q117498

1.00 1.50 WINDOWS kbtool kbbuglist

The information in this article applies to:

SYMPTOMS

A custom-based new(), delete(), and new handler do not receive correct parameters in small-memory or medium-memory models. The new handler's parameters are reversed. For new() and delete(), the offset of the address of the segment, rather than the value of the segment, is pushed onto the stack.

CAUSE

The generated code assumes that __segment is based in DS (default data segment). The code provides a fixup for the segment variable that is the first formal argument.

RESOLUTION

Switch to the compact-memory, large-memory, or huge-memory model.

STATUS

Microsoft has confirmed this to be a bug in the products listed at the beginning of this article. We are researching this bug and will post new information here in the Microsoft Knowledge Base as it becomes available.

MORE INFORMATION

The sample code below demonstrates this problem. To fix the problem, compile the following sample code using /AC or /AL.

Sample Code

/* Compile options needed: none
*/ 

   #include <iostream.h>
   #include <malloc.h>
   #include <new.h>
   #include <stdlib.h>
   #include <string.h>

   __segment test_seg;
   char __based(test_seg) *a;

   void __based(void) *operator new( __segment seg, size_t size);
   void operator delete(__segment seg, void __based(void) *ptr);
   void test(void);

   int NewHandler(__segment s, size_t size )
   {
      // WARNING: The arguments are backwards.
      // s == the size and size == the segment.
      cerr << "\n\aCan't allocate " << (size_t)s << " bytes." << endl;
      exit(1);
      return 0;
   }

   void main()
   {
      _set_bnew_handler(NewHandler);

      if ((test_seg = _bheapseg(10000)) == _NULLSEG)
      {
         cout << "bheapseg failure!  Bailing..." << endl;
         exit(1);
      }
      test();
   }

   void test()
   {
      a = new __based(test_seg) char[100];

      if (a == _NULLOFF)
      {
         cout << "_bmalloc failure." << endl;
         return;
      }

   #if defined (M_I86LM) || (M_I86CM) || (M_I86HM)
      strcpy(a, "Greetings");
      cout << a << endl;
   #else // Small & Medium model
   #pragma message ("WARNING: <<small and medium model application>>")
   #pragma message ("CRT routines may not reference based data properly.")
   #endif

      delete a;
   }

   void __based(void) *operator new( __segment offset, size_t size)
   {
      unsigned MYDS;
      unsigned long addr;

      _asm    mov  ax, ds
      _asm    mov  MYDS, ax
      addr = (unsigned long)MYDS;
      addr <<= 16;
      __segment bseg = *(__segment *)(addr | (unsigned long)offset);

      return _bmalloc( bseg, size);
   }

   void operator delete(__segment offset, void __based(void) *ptr)
   {
      unsigned MYDS;
      unsigned long addr;

      _asm    mov  ax, ds
      _asm    mov  MYDS, ax
      addr = (unsigned long)MYDS;
      addr <<= 16;
      __segment bseg = *(__segment *)(addr | (unsigned long)offset);

      _bfree(bseg, ptr);
   }

Additional reference words: 1.00 1.50 8.00 8.00c KBCategory: kbtool kbbuglist KBSubcategory: CPPIss Keywords : kb16bitonly

Last Reviewed: July 23, 1997