Hello,

Okay, since I am only experimenting with Visual C++ I should not be
extremely strict, but what I found will surprise many. I was _very_
surprised.

In case this bug is known (I couldn't find it reported, though), ignore my
report.
In case you find the code being in error - it is supposed to be 100%
Standard C++ - tell me and I'll take a break from C++.
I am using Visual C++ 2005 Express Edition.


First of all, here the code:


#include <iostream>
#include <ostream>
#include <utility>

int main()
{
typedef unsigned long bug_type;

bug_type a = 2;
bug_type b = 34;
bug_type c = 534;

bug_type d = std::max(std::max(a, b), c);

std::cout << "max value: " << d << "\n";
}


Create a new Win32 console project. I created mine without precompiled
headers and empty, but I don't think it matters (haven't tried it though).
Do not modify any project properties.

Add the code to the project, compile in Debug and Release mode. Output is as
expected.

Now set "project properties -> Configuration Properties -> C++ ->
Language -> Disable Language Extensions" to true.
Compile again in Debug and Release mode, also pay attention to warning
issued.
Now run both programs, and take a look at the output in debug mode and
release mode.


Now some properties of the bug:

1) It does not happen if some other type (e.g. int, long) is used as
bug_type.

2) It does not happen if there is only one std::max, e.g. the following
line:
bug_type d = std::max(a, b);
does not cause symptorms

3) It does not appear when language extensions are disabled (default)

4) It only appears in debug mode.


I find this really cool. Cool because such a simply bug, cool because it
took ages to track it down, cool because it vanishes in release mode.
If someone knows a prize for me, I will happily take one :-)


I will report it to the Microsoft page if people here agree that:
a) it is a bug, not my code being wrong
b) it is not reported
c) it can be reproduced on other machines

I wait with reporting because it looks so strange I believe I am dreaming.
Tell me if I am not.


Thomas

Re: std::max by Thomas

Thomas
Tue Apr 11 16:35:44 CDT 2006


"Thomas Mang" <a9804814@unet.univie.ac.at> schrieb im Newsbeitrag
news:443c1e27$0$12642$3b214f66@usenet.univie.ac.at...

> In case you find the code being in error - it is supposed to be 100%
> Standard C++ - tell me and I'll take a break from C++.

A self-puristic note:
I included the wrong header, it should be <algorithm> instead of <utility>.

Please change the program #including <algorithm> to make it really 100% C++.


The whole bug issue remains, of course.


Thomas



Re: std::max by Victor

Victor
Tue Apr 11 16:47:53 CDT 2006

Thomas Mang wrote:
> "Thomas Mang" <a9804814@unet.univie.ac.at> schrieb im Newsbeitrag
> news:443c1e27$0$12642$3b214f66@usenet.univie.ac.at...
>
>> In case you find the code being in error - it is supposed to be 100%
>> Standard C++ - tell me and I'll take a break from C++.
>
> A self-puristic note:
> I included the wrong header, it should be <algorithm> instead of
> <utility>.
> Please change the program #including <algorithm> to make it really
> 100% C++.
>
> The whole bug issue remains, of course.

Here is what they do:

template<class T> T const& max(T const& a, T const& b)
{
return a > b ? a : b;
}

#include <cassert>
int main()
{
typedef unsigned long bug_type;

bug_type a = 2;
bug_type b = 34;
bug_type c = 534;

bug_type d = max(max(a, b), c);
assert(d == 534);
}

I believe the problem is with temporary objects dying before being
used. The debug implementation of 'std::max' is rather strange in
that regard. Why use references?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask



Re: std::max by Carl

Carl
Tue Apr 11 22:25:49 CDT 2006

Thomas Mang wrote:
> "Thomas Mang" <a9804814@unet.univie.ac.at> schrieb im Newsbeitrag
> news:443c1e27$0$12642$3b214f66@usenet.univie.ac.at...
>
>> In case you find the code being in error - it is supposed to be 100%
>> Standard C++ - tell me and I'll take a break from C++.
>
> A self-puristic note:
> I included the wrong header, it should be <algorithm> instead of
> <utility>.
> Please change the program #including <algorithm> to make it really
> 100% C++.
>
> The whole bug issue remains, of course.

Definitely a bug. Here's the smallest repro I could come up with (VS2005
Team Suite):

// code
#include <stdio.h>
typedef unsigned long bug_type;
bug_type const& max(bug_type const& a, bug_type const& b)
{
return a > b ? a : b;
}

int main()
{
bug_type a = 2;
bug_type b = 34;
bug_type c = 534;
bug_type d = max(max(a, b), c);
printf("max value %i\n",d);
}
// end of code

compile with:

cl /RTC1 /MDd /Za /FAsc .\maxbug0411.cpp

The bug is an interaction between /RTC1 and /Za - remove either, and the bug
goes away.

Please file a bug report and post a link to it here so others can validate
and vote on it.

-cd



Re: std::max by Thomas

Thomas
Wed Apr 12 01:16:10 CDT 2006


"Carl Daniel [VC++ MVP]" <cpdaniel_remove_this_and_nospam@mvps.org.nospam>
schrieb im Newsbeitrag news:eg93MDeXGHA.2376@TK2MSFTNGP03.phx.gbl...
>
> Please file a bug report and post a link to it here so others can validate
> and vote on it.


Done.
I quoted your sample program too.

link is:
http://tinyurl.com/frjp6



Thomas



Re: std::max by Thomas

Thomas
Wed Apr 12 09:11:36 CDT 2006


"Victor Bazarov" <v.Abazarov@comAcast.net> schrieb im Newsbeitrag
news:eAwEXGbXGHA.4144@TK2MSFTNGP04.phx.gbl...
> Thomas Mang wrote:
>> "Thomas Mang" <a9804814@unet.univie.ac.at> schrieb im Newsbeitrag
>> news:443c1e27$0$12642$3b214f66@usenet.univie.ac.at...
>>
>>> In case you find the code being in error - it is supposed to be 100%
>>> Standard C++ - tell me and I'll take a break from C++.
>>
>> A self-puristic note:
>> I included the wrong header, it should be <algorithm> instead of
>> <utility>.
>> Please change the program #including <algorithm> to make it really
>> 100% C++.
>>
>> The whole bug issue remains, of course.
>
> Here is what they do:
>
> template<class T> T const& max(T const& a, T const& b)
> {
> return a > b ? a : b;
> }
>
> #include <cassert>
> int main()
> {
> typedef unsigned long bug_type;
>
> bug_type a = 2;
> bug_type b = 34;
> bug_type c = 534;
>
> bug_type d = max(max(a, b), c);
> assert(d == 534);
> }
>
> I believe the problem is with temporary objects dying before being
> used. The debug implementation of 'std::max' is rather strange in
> that regard. Why use references?


As Carl Daniel has shown, the bug is not in the Standard Lib-implementation
of max, min or some other.

The signature you have shown is the one the Standard requirees.
You could also safely pass in temporaries (which I didn't, I provided
l-values), because the temporaries bound to the reference to const will be
destroyed at the end of the full expression, therefore the return value is
OK.

Thomas



Re: std::max by Carl

Carl
Wed Apr 12 10:45:52 CDT 2006

Thomas Mang wrote:
> "Victor Bazarov" <v.Abazarov@comAcast.net> schrieb im Newsbeitrag
>> Here is what they do:
>>
>> template<class T> T const& max(T const& a, T const& b)
>> {
>> return a > b ? a : b;
>> }
>>
>> I believe the problem is with temporary objects dying before being
>> used. The debug implementation of 'std::max' is rather strange in
>> that regard. Why use references?
>
> The signature you have shown is the one the Standard requirees.
> You could also safely pass in temporaries (which I didn't, I provided
> l-values), because the temporaries bound to the reference to const
> will be destroyed at the end of the full expression, therefore the
> return value is OK.

Yeah, it is the signature that the Standard requires, but it's less than
optimal in the case of built-in types like unsigned long.

Now that VC++ fully supports type traits (at least the compiler primitives,
not yet std::tr1::type_traits, but that's coming) it'd be nice to see an
implementation of std::min and max that intelligently chooses between pass
by value and pass by reference depending on the type(s) involved.

-cd



Re: std::max by Thomas

Thomas
Wed Apr 12 14:10:24 CDT 2006


"Carl Daniel [VC++ MVP]" <cpdaniel_remove_this_and_nospam@mvps.org.nospam>
schrieb im Newsbeitrag news:eg93MDeXGHA.2376@TK2MSFTNGP03.phx.gbl...


I noticed you added a comment to my bug report, explaining the issue more
detailedly at generated instructions level.
Since the title of my report does not seem appropriate, I think it should be
changed.

Note also [I completely forgot to try that out] not only initialization is
affected, by assignment too:

bug_type d = 0;

d = max(max(a, b), c);

d is overwritten again by 0xCCCCCCCC.

[I do not know if you have the right to do so, since you did not create it.
Anyways, either feel free to change it yourself if you can, or suggest a
good title here and I'll change the title.]


Thomas



Re: std::max by Carl

Carl
Wed Apr 12 15:43:01 CDT 2006

"Thomas Mang" <a9804814@unet.univie.ac.at> wrote in message
news:443d509b$0$8024$3b214f66@usenet.univie.ac.at...
>
> "Carl Daniel [VC++ MVP]" <cpdaniel_remove_this_and_nospam@mvps.org.nospam>
> schrieb im Newsbeitrag news:eg93MDeXGHA.2376@TK2MSFTNGP03.phx.gbl...
>
>
> I noticed you added a comment to my bug report, explaining the issue more
> detailedly at generated instructions level.
> Since the title of my report does not seem appropriate, I think it should
> be changed.
>
> Note also [I completely forgot to try that out] not only initialization is
> affected, by assignment too:
>
> bug_type d = 0;
>
> d = max(max(a, b), c);
>
> d is overwritten again by 0xCCCCCCCC.
>
> [I do not know if you have the right to do so, since you did not create
> it.
> Anyways, either feel free to change it yourself if you can, or suggest a
> good title here and I'll change the title.]

I couldn't really think of a succinct title, so I left it be. I think it's
good enough to get the point across.

-cd



Re: std::max by Carl

Carl
Mon Apr 24 00:26:27 CDT 2006

For anyone still watching this thread - this bug is fixed in current
internal builds of the compiler.

-cd