BUG: Array-Style New Allocates Wrong Number of Objects

Last reviewed: July 22, 1997
Article ID: Q113428
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

Unexpected results may occur due to errors in the code generated by using any one of the following optimizations: /O2, /O1, /Og, /Oe, /Ol, or /Ox. This problem may be reproduced by using the C++ "new" operator to allocate memory for an array of objects, assuming that the following criteria are also satisfied:

  • A "default" constructor is explicitly supplied for the object class.
  • A destructor is not explicitly provided for the class.
  • A nonconstant expression is used for the array size in the "new" invocation.

CAUSE

The optimizing compiler is generating incorrect code. This may be seen by creating a .COD listing file by adding /Fc to the compiler options. Depending on the optimization used, the code generated to call "new" will not be passed the correct value.

RESOLUTION

Any of the following will correct this condition for the specific example provided below:

  • Use the fast (/f) compiler instead of the optimizing compiler.

    -or-

  • Disable the optimization for the duration of the function that calls the C++ "new" operator.

    -or-

  • Do not provide a default constructor for the class.

    -or-

  • Provide a destructor for the class.

    -or-

  • Use a constant expression for the array size (make "n" a "const" or supply an explicit value instead).

STATUS

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

MORE INFORMATION

Sample Code

/* Compile options needed: /f- and /Ox
   Actually, any one of /O2, /O1, /Og, /Oe, /Ol, or /Ox
   will cause the problem.
*/

//---------------------------------------------------------
// Sample to demonstrate code generation problem
//---------------------------------------------------------

#include <iostream.h>

class AnyName { public:
    AnyName() { nTimesCalled++; };
    static int nTimesCalled;
};

int AnyName::nTimesCalled = 0;

//---------------------------------------------------------
// main() calls 'new' to demonstrate the problem
//---------------------------------------------------------

void main()
{
    int n = 20;    // Indicates the number of
                   // objects to construct

    AnyName *pAnyName = new AnyName [n];

    cout << "Results: " << endl
         << "  Constructor was called " << AnyName::nTimesCalled
         << " times." << endl
         << "  Constructor should have been called "
         << (n) << " times." << endl;

    if ( AnyName::nTimesCalled == (n) )
        cout << "  Constructor called correct number of times!"
             << endl << endl;
    else
        cout << "  Constructor called incorrect number of times!"
             << endl << endl;
}


Additional reference words: 1.00 1.50 8.00 8.00c
KBCategory: kbtool kbbuglist
KBSubcategory: CPPIss
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.