By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,276 Members | 2,137 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,276 IT Pros & Developers. It's quick & easy.

Optimizer bug (VC6 and VC7.1)?

P: n/a
Hi,

Would it be fair to say the following is an optimizer bug?

--- Test.cpp ---

#include <cstdio>

using std::printf;

typedef int* IntPointer;

class CTestClass
{
public:

CTestClass(const IntPointer& pInt) : m_pInt(pInt)
{
}

virtual Test()
{
}

const IntPointer& m_pInt;

};

int main()
{
int x = 0xFF;

CTestClass Test(&x);

printf("&x = %p, Test.m_pInt = %p\n", &x, Test.m_pInt);

// Note the different address

// *Test.m_pInt = 0; // CRASH

return 0;
}

------

This is the output with optimizations (note the different addresses):

D:\>cl /O2 Test.cpp & test
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
[...]

&x = 0012FEE4, Test.m_pInt = 000000FF
This is the output without optimizations:

D:\>cl Test.cpp & test
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
[...]

&x = 0012FED8, Test.m_pInt = 0012FED8
I have been able to determine that the following criteria are necessary:

- class has a vtable
- constructor is inline
- variable is passed as a reference

Turning off global optimizations /Og or inlining prevents the issue. This
happens on VC6.0 SP6 as well as VC7.1.

I don't believe I am doing anything illegal.

Thanks
Brian
Nov 17 '05 #1
Share this Question
Share on Google+
2 Replies


P: n/a
Brian Ross wrote:
Hi,

Would it be fair to say the following is an optimizer bug?
I think your code is undefined, so I'd hesitate to call it an optimizer bug.
See below.
--- Test.cpp ---

#include <cstdio>

using std::printf;

typedef int* IntPointer;

class CTestClass
{
public:

CTestClass(const IntPointer& pInt) : m_pInt(pInt)
{
}

virtual Test()
{
}

const IntPointer& m_pInt;

};

int main()
{
int x = 0xFF;

CTestClass Test(&x);

printf("&x = %p, Test.m_pInt = %p\n", &x, Test.m_pInt);

// Note the different address

// *Test.m_pInt = 0; // CRASH

return 0;
}

------

This is the output with optimizations (note the different addresses):

D:\>cl /O2 Test.cpp & test
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
[...]

&x = 0012FEE4, Test.m_pInt = 000000FF
This is the output without optimizations:

D:\>cl Test.cpp & test
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
[...]

&x = 0012FED8, Test.m_pInt = 0012FED8
I have been able to determine that the following criteria are necessary:

- class has a vtable
- constructor is inline
- variable is passed as a reference

Turning off global optimizations /Og or inlining prevents the issue. This
happens on VC6.0 SP6 as well as VC7.1.

I don't believe I am doing anything illegal.


You're binding the pointer produced by &x to a const reference. This is a
temporary pointer, and it goes away at the end of the statement:

CTestClass Test(&x);

This invalidates Test's m_pInt member, which is a reference bound to the
temporary, and so using m_pInt once the ctor returns is undefined. My rule
of thumb regarding const reference parameters is to never copy them to a
reference member or other long-lived reference variable, which avoids this
problem. Non-const reference parameters don't suffer from this problem in a
conformant compiler, because such a compiler disallows binding a temporary
to a non-const reference.

Why don't you simply pass the pointer by value? I hope you realize that:

CTestClass(const IntPointer& pInt)

means:

CTestClass(IntPointer const & pInt)

or simply:

CTestClass(int* const & pInt)

I don't see what using a reference buys you here.

--
Doug Harrison
Microsoft MVP - Visual C++
Nov 17 '05 #2

P: n/a

"Doug Harrison [MVP]" <ds*@mvps.org> wrote in message
news:66********************************@4ax.com...
Brian Ross wrote:
Hi,

Would it be fair to say the following is an optimizer bug?
I think your code is undefined, so I'd hesitate to call it an optimizer

bug. See below. You're binding the pointer produced by &x to a const reference. This is a
temporary pointer, and it goes away at the end of the statement:

CTestClass Test(&x);

This invalidates Test's m_pInt member
Hmm.. I believe you may be correct. I never considered that I was producing
a temporary value. :) I will have to update my code appropriately.

This is why I posted here. You never know when you will be enlightened on
what you missed or assumed. :)
Why don't you simply pass the pointer by value? I hope you realize that:

CTestClass(const IntPointer& pInt)

means:

CTestClass(IntPointer const & pInt)

or simply:

CTestClass(int* const & pInt)

I don't see what using a reference buys you here.


This had to do with how the original problem was encountered. The class was
actually a template where the type of the parameter was based on the
template parameter. I simplified the code as much as I could while still
reproducing the problem which meant I had to keep the reference parameter. I
see now why the problem went away when I took away the reference.

Thanks :)

Brian
Nov 17 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.