none
Possible bug relating to default value

    Question


  • The following program demonstrates a possible issue when using default parameters coupled with template functions or methods.

    The expected value of the default parameter c should be ZERO for both invocations foo() however it seems like a different value is set.

     

    #include <cstdio>
    #include <cstddef>
    
    template<typename T>
    void foo(const T& c = T(0.0));
    
    template<typename T>
    void foo(const T& c)
     {
    	printf("sizeof(T) = %d\n", sizeof(T));
    	printf("is zero: %s\n", c == T(0.0) ? "yes" : "no");
    	unsigned char *s = reinterpret_cast<unsigned char *>(&s);
    	for (std::size_t i = 0; i < sizeof(T); i++)
    		printf("%02x ", s[i]);
    	printf("\n");
    }
    
    int main()
    {
    	foo<float >();
    	foo<double>();
    	return 0;
    }

     

     

     

    if invoked in the order given i.e. foo<float>() followed by foo<double>() the issue occurs on the invocation of foo<double>(). Any other order where foo<double>() is invoked first the issue is not present. The erroneous value that is being passed in for the foo<double>() invocation seems to contain uninitialised data.

    Also note that removing the declaration of foo and placing the default parameter into the definition eliminates the issue.

    It works as expected under gcc 4.3.2 and gcc 3.4.6.

    It seems the default value is being ignore in some situations. Interestingly too if I replace T(0.0) with say another function like const zero<T>() it doesnt make any difference. Even going further and providing specialised versions of a zero function doesnt help.

    The dissassembly shows the same code being used for both <float> and <double> invocations.

    Visual Studio info:

    Microsoft Visual Studio 2008
    Version 9.0.21022.8 RTM
    Microsoft .NET Framework
    Version 3.5 SP1

    Microsoft Visual C++ 2008   91605-270-9801532-60417
    Microsoft Visual C++ 2008

    Thursday, August 13, 2009 5:57 AM

Answers

All replies

  • Good morning Color_Of_Green

     

    The problem can be reproduced on my side. I suggest reporting it on Visual Studio feedback site:

    https://connect.microsoft.com/VisualStudio/?wa=wsignin1.0

    Visual C++ product team will follow up with you.

     

    I will also try to report the issue to the product team through internal channels. If there are any findings on my side, I will update you.

     

    Thanks for the report

     

    Thanks,

    Jialiang Ge

    MSDN Subscriber Support in Forum

    If you have any feedback of our support, please contact msdnmg@microsoft.com.  

     

     


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Thursday, August 13, 2009 10:21 AM
    Moderator
  • You've found a bug in the compiler.  It should have generated a compile error on your code but didn't.  Slugging along, it generates bad code.  It's okay for the float template type argument:

    010914F7  mov         eax,dword ptr [ebp+8]   ; eax => argument c
    010914FA  fld         dword ptr [eax]                 ; ST(0) = c
    010914FC  fcomp       qword ptr ds:[01095740h] ; etc...


    But not for double:

    00221657  mov         eax,dword ptr [ebp+8]  ; eax => argument c
    ; no fld instruction here!!!
    0022165A  fldz                                                ; etc...

    The bug is specific to templates, you get the proper error on this:

    void test(double& c = (double&)0.0) {
      printf("%f", c);
    }

    There's an oops in your dumping code btw, it should look like this:

        unsigned char *s = reinterpret_cast<unsigned char *>(const_cast<T*>(&c));


    The workaround is simple enough, make your template legal C++ code:

    template<typename T>
    void foo(const T c = T(0.0));

    You can report the bug at connect.microsoft.com. 

    Hans Passant.
    Thursday, August 13, 2009 11:13 AM
    Moderator

  • Thanks for the help,

    I don't quite follow the part which is illegal.

    I understand that with T = double the following would be illegal:
    void test(double& c = (double&)0.0) {
      printf("%f", c);
    }

    but since the cast is to double (not double&) it should become:

    void test(const double& c = double(0.0)) {
      printf("%f", c);
    }

    which produces the correct result outside templates.

    Thursday, August 13, 2009 11:57 AM
  • Thursday, August 13, 2009 12:21 PM
  • Hello Luke

    I have recorded this issue into the product database. The product team will follow up you in the feedback site. As a workaround of the issue, please try function overloading. For example,

    template<typename T>
    inline void foo(const T& a, const T& b);
    template<typename T>
    inline void foo(const T& a, const T& b, const T& c);


    template<typename T>
    inline void foo(const T& a, const T& b)
    {
     foo(a, b, T(0.0));
    }

    template<typename T>
    inline void foo(const T& a, const T& b, const T& c)
    {
     printf("sizeof(T) = %d\n", sizeof(T));
     printf("is zero: %s\n", c == T(0.0) ? "yes" : "no");
     unsigned char *s = reinterpret_cast<unsigned char *>(&s);

     printf("\n");
    }

    template<typename T>
    inline void bar(const T& a, const T& b)
    {
     foo(a,b);
    }


    int _tmain(int argc, _TCHAR* argv[])
    {
     bar<float >(1.0f, 1.0f);
     bar<double>(1.0 , 1.0 );
    }

    If you have any other questions or concerns, please feel free to tell me.

    Thanks,
    Jialiang Ge
    MSDN Subscriber Support in Forum
    If you have any feedback of our support, please contact msdnmg@microsoft.com.  


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Friday, August 14, 2009 5:57 AM
    Moderator
  • Hello Luke

    I notice that VC++ product team has updated you in the feedback site:
    https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=482753

    Thank you for this bug report. This indeed is a bug in our VS2008SP1 compiler, and we will make sure it is fixed in the next version of the compiler. Can you please move the default parameter to the definition of the function.

    May I know if my workaround is useful to you or not? If you have any other questions or concerns, please feel free to post here or in the feedback page. Thanks for the report.

    Thanks,
    Jialiang Ge
    MSDN Subscriber Support in Forum
    If you have any feedback of our support, please contact msdnmg@microsoft.com.  


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Monday, August 17, 2009 12:07 PM
    Moderator