BUG: The default behavior of the for statement destroys the object incorrectly (823841)



The information in this article applies to:

  • Microsoft Visual C++ .NET (2002)

SYMPTOMS

When you declare an object in the init-expression element of the for loop in Microsoft Visual C++ .NET 2002, and the object is used outside the scope of the for statement, you may receive unwanted results. Note In Microsoft Visual C++ .NET 2003, you may receive the following compiler error message:
error C2065: <variable name> : undeclared identifier

CAUSE

In Visual C++ .NET 2002, when the object is created in the init-expression element of the for statement, the object is destroyed as the object goes outside the scope of the for statement. This behavior occurs even though the object is accessible outside the scope of the for statement.

RESOLUTION

When you migrate an existing Visual C++ 6.0 project to Visual C++ .NET 2002, always compile the migrated project in Visual C++ .NET 2002 with the /Zc:forScope compiler option. When you use the the /Zc:forScope compiler option, you may receive a compiler error message while compiling the project. For each object that you receive a compiler error for, declare the object before the for statement. The following is the modified code:
MyClass mc = 10;
for(;mc;--mc)
{
}
printf("Value of mc.m_i = %d\n",mc.m_i);

STATUS

Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.

MORE INFORMATION

Steps to Reproduce the Behavior

  1. Start Visual Studio .NET 2002.
  2. On the File menu, point to New, and then click Project.
  3. Click Visual C++ Projects under Project Types, and then click Win32 Console Application under Templates.
  4. Paste the following code in the .cpp project:
    class MyClass
    {
    
    public:
    	int m_i;
        MyClass(int i):m_i(i)
        {
            printf("From the constructor = %d\n",m_i);
        }
        ~MyClass()
        {
            printf("From The destructor = %d\n", m_i);
        }
        operator bool ()
        {
            return m_i != 0?true:false;
        }
        MyClass& operator-- ()
        {
            --m_i; 
            return *this;
        }
    };
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        for(MyClass mc = 10;mc;--mc)
        {
        }
        printf("Value of mc.m_i = %d\n",mc.m_i);
        return 0;
    }
  5. Press the CTRL + F5 key combination to compile and to run the project. You may receive the following output in the Console window:
    From the constructor = 10
    From The desctructor = 0
    Value of mc.m_i = 0
Notice that the object is destroyed as it goes outside the scope of the for statement.

Note According to the C++ standards (Section 6.5.3.3 of ISO:IES 14882:1998 E), the variable that is declared in the init-expression of the for statement has a scope that is limited to the scope of the for statement. Accessing the variable outside the scope of the for statement causes undefined behavior.

By default, under /Ze (Microsoft Extension for C++), a variable that is declared in a for statement remains in scope until the enclosing scope ends for the for statement.

Visual C++ 6.0 does not destroy the object because the object goes outside the scope of the for statement.

Be careful when you convert a project from Visual C++ 6.0 to Visual C++ .NET 2002. Generally, you declare and initialize Standard Template Library ( STL) iterators in the init-expression element of the for statement, and when you compile and run the converted projects in Visual C++ .NET 2002, you may receive unwanted results.

REFERENCES

For additional information about the Microsoft extensions for C++ language, visit the following Microsoft Developer Network (MSDN) Web site:For additional information about the C++ Compiler, Linker, and C++ Language, visit the following MSDN Web site:For additional information about the for statement, visit the following MSDN Web site:

Modification Type:MinorLast Reviewed:12/30/2005
Keywords:kberrmsg kbCompiler kbconvert kbbug KB823841 kbAudDeveloper