Jump to content
  • Advertisement
Sign in to follow this  
Mantear

C++ MSVS 2005 Express compiler bug?

This topic is 4126 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Greetings! I've got a real head-scratcher here as to why the compiler (MSVS 2005 Express) is compiling something with no errors. Here's the class:
class TestClass
{
public:
    TestClass(){m_Width = 0;}
    ~TestClass(){}
    unsigned int Width(){ return m_Width; }
    void Width(unsigned int width){ m_Width = width; }

private:
    unsigned int m_Width;
};
I made the following mistake in my code:
TestClass object;
if (object.Width > 0)
{ ... }
else
{ ... }
This code snippet compiled with no errors or warnings! It was failing the check that it was supposed to pass and processing the else statement, causing me to take a closer look at that section when I noticed the missing '()'. Even run-time there was no indication of anything going wrong other than the check failing when it shouldn't have. If I remove either declarations of Width(), it won't compile with the normal expected errors. What's going on here?

Share this post


Link to post
Share on other sites
Advertisement
Sometimes Visual C++ (I've noticed this in every version) gets into a strange state that only rebuilding the entire project can fix.

Share this post


Link to post
Share on other sites
It's correct behvaior, but obviously not what you wanted. What it's actually doing is comparing the function istelf (a pointer to that function) to zero. Depending on the address of the code (which probably is an address like 0x8...), the value (when interpreted as a signed value) is negative, so the else clause is taken.

It's an obnoxious bug that comes up every so often. In many cases, the necessary casting to trigger this problem causes the compiler to emit a warning or error. But in some cases (like this one), the surrounding code is simple enough that it just happens silently.

Share this post


Link to post
Share on other sites
Quote:
It's correct behvaior, but obviously not what you wanted. What it's actually doing is comparing the function istelf (a pointer to that function) to zero.

A valiant attempt, but this is not the case here. Forming a pointer-to-member would be required to compare the function's address to zero, and that requires explicit use of the address-of operator and a slightly different syntax in general.

To the OP, there is more to your problem then you have extracted and shown here.
The following code, identical to yours but for the creation of a main() function to hold the offending code, produces error C3867 (complaining that Width() is missing a function call argument list) as expected:

#include <iostream>

class TestClass
{
public:
TestClass(){m_Width = 0;}
~TestClass(){}
unsigned int Width(){ return m_Width; }
void Width(unsigned int width){ m_Width = width; }

private:
unsigned int m_Width;
};

int main()
{
TestClass object;
if (object.Width > 0)
{
std::cout << "TRUE";
}
else
{
std::cout << "FALSE";
}
}


Perhaps you have a macro in scope that is doing something funky? Try to pare down the example further.

Share this post


Link to post
Share on other sites
1>.\Main.cpp(16) : error C3867: 'TestClass::Width': function call missing argument list; use '&TestClass::Width' to create a pointer to member

That's what my VS2k5 SP1 tells me.
Some compilers sometimes lets you get away with omitting the & to get a function pointer, which might be what you're experiencing.

Share this post


Link to post
Share on other sites
Entire source code of a test project using VisualC++ 2005 Express Edition (Version 8.0.50727.42)

Header: TestClass.h
class TestClass
{
public:
TestClass(){m_Width = 10;}
~TestClass(){}
unsigned int Width(){ return m_Width; }
void Width(unsigned int width){ m_Width = width; }

private:
unsigned int m_Width;
};


Source: TestClass.cpp
// TestClass.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "TestClass.h"

int _tmain(int argc, _TCHAR* argv[])
{
TestClass object;
bool success;

if (object.Width > 0)
{
success = true;
}
else
{
success = false;
}

return 0;
}


Build results:
------ Build started: Project: TestClass, Configuration: Debug Win32 ------
Compiling...
stdafx.cpp
Compiling...
TestClass.cpp
Compiling manifest to resources...
Linking...
Embedding manifest...
Build log was saved at "file://c:\3dEngine\Test\TestClass\TestClass\Debug\BuildLog.htm"
TestClass - 0 error(s), 0 warning(s)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========


Running the program takes it down the
success = false
path.
???

Share this post


Link to post
Share on other sites
The fact that Zao and I are using SP1 might be the difference -- perhaps an appropriate extension to allow pointer-to-member to be formed without the address-of was removed in SP1. I'm somewhat skeptical of that, however, but I haven't dug up a changelist to see.

You could try going to the project options and disabling language extensions to see if it fails then. Also, what's in stdafx.h or anything included by stdafx.h?

Share this post


Link to post
Share on other sites
I tried it with Language Extensions disabled (/Za) but nothing changed.

stdafx.h is the default file generated by VS. It's contents are:
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#pragma once


#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <stdio.h>
#include <tchar.h>



// TODO: reference additional headers your program requires here


How do I go about getting SP1? What are the main improvements with SP1?

Share this post


Link to post
Share on other sites
It compiles for me :(
No SP1, fresh VS install.
Disabled precompiled header.

Even after I examined generated asembly, I cannot find what it's doing:
//... object has just been constructed (eax=this)
0040103E xor eax,eax
00401040 je main+18h (401048h) // else

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!