CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 13 of 13
  1. #1
    Join Date
    Aug 2009
    Posts
    440

    [RESOLVED] Variable assigned wrong value?

    Consider the following:

    Code:
    float foo( float const *bar )
        )
    {
        float temp;
        temp = *bar; 
        ...
    }
    Something I am noticing is that temp right after the assignment to *bar, is not the same value as *bar. Has anyone seen anything like this before? This is for a project at work and the code runs on an embedded board with an ARM processor. I've copied the function into a standalone program for both Visual Studio and Code::Blocks and it works correctly there. Thanks for any insight.

  2. #2
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Variable assigned wrong value?

    Quote Originally Posted by Alterah View Post
    Something I am noticing is that temp right after the assignment to *bar, is not the same value as *bar.
    1) Define "not the same value".

    2) Are you debugging an optimized build? If you are, then you can't determine the flow of the code, what variables have been moved or removed, etc. by looking at the original source code.

    Bottom line is -- does the function work? If it does, then the issue is more than likely the code has been optimized.

    Regards,

    Paul McKenzie

  3. #3
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: Variable assigned wrong value?

    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  4. #4
    Join Date
    Aug 2009
    Posts
    440

    Re: Variable assigned wrong value?

    The purpose of the function (the real function) is to force any angle (in radians) to be between -pi and pi. The value passed into the function is pi/4. The value that is assigned to temp is ~ pi / 4000. However, as strange as this is, turns out even though temp doesn't appear to get assigned the correct value, the function itself is returning the correct value (according to the value in the registers).

    What is happening is that the return value for the function is assigned to a variable. In between this assignment, the compiler, for some reason is performing an implicit conversion from an int to a float. What we have is essentially:

    Pseudocode...
    Code:
    float radians = intvalue * floatvalue;
    radians = foo( &radians );
    Looking at the assembly, foo returns the correct float value, but the compiler is doing an implicit conversion. I am not at work anymore, but I should have more information tomorrow that I can share.

  5. #5
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Variable assigned wrong value?

    Quote Originally Posted by Alterah View Post
    The purpose of the function (the real function) is to force any angle (in radians) to be between -pi and pi. The value passed into the function is pi/4. The value that is assigned to temp is ~ pi / 4000. However, as strange as this is, turns out even though temp doesn't appear to get assigned the correct value, the function itself is returning the correct value (according to the value in the registers).
    Please post the smallest, real (not psuedo-code), but complete example that has this behaviour.

    Secondly, actually print out the value of "temp" (printf, cout, etc.). Do not rely on what you see in the debugger, as again, the code could have been optimized (or that the debugger may not be working correctly).

    If "temp" is so off, then what would happen if you really used "temp" for other calculations, or even as output (as I mentioned)? If "temp" prints out a completely bogus number, then take that code and present it to the engineers of the compiler, as that would mean the compiler is severely broken.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; November 15th, 2012 at 09:30 PM.

  6. #6
    Join Date
    Aug 2009
    Posts
    440

    Re: Variable assigned wrong value?

    What I discovered after digging a bit deeper is that it doesn't actually look like temp is being assigned the wrong value.

    Here's the code, as best as I can remember it:

    Code:
    #include <iostream>
    
    using namespace std;
    
    const float PI = 3.14159265359;
    
    float restrictAngle( float const *angle )
    {
        int circles;
        float temp;
    
        circles = (int)( *angle / ( 2 * PI ) );
        temp = *angle - ( circles * 2 * PI );
    
        if( temp > PI )
        {
            temp -= ( 2 * PI );
        }
        else if( temp < (-PI) )
        {
            temp += ( 2 * PI );
        }
    
        return temp;
    }
    
    int main()
    {
        float radians;
        int temp = 1;
        radians = temp * ( 45.0 * PI / 180.0 );
        radians = restrictAngle( &radians );
    }
    Now, with this code, the value we assign to radians shouldn't change between the first and second assignment. However, what I am seeing with this code compiled via ARM, is that we get the return value for restrictAngle, and before we actually store that value into radians, we convert it from an int to a float. This conversion causes radians to get assigned a very large number (I cannot remember the number off the top of my head). I know this happening because when I run the actual code without the debugger, the behavior of the embedded device is not what it should be. I hope this helps to illuminate the issue I am seeing. It's not something that I think is easy to describe. Thanks again.

  7. #7
    Join Date
    Nov 2012
    Location
    Kolkata, WestBengal, India
    Posts
    15

    Re: Variable assigned wrong value?

    As I was looking into your code, I have found this line bit strange -
    circles = (int)( *angle / ( 2 * PI ) );
    As I was debugging the data comes as -
    radians = temp * ( 45.0 * PI / 180.0 ); ==>> 0.78539819
    and
    *angle / ( 2 * PI ) ==>> 0.12500000000000000
    which when casted to int, it becomes -
    circles = (int)( *angle / ( 2 * PI ) ); ==>> 0

    So, ( circles * 2 * PI ) ==>> 0
    Hence temp becomes -
    temp = *angle - ( circles * 2 * PI ); ==>> *angle ==>> 0.78539819

    So, this value doesn't satisfies any of the if condition here -
    if ( temp > PI ) ==> FALSE
    if( temp < (-PI) ) ==>> FALSE

    hence it only returns temp = 0.78539819
    hence final value for radians becomes 0.78539819

    Is this what you were looking for? Hope I am not missing something here.

  8. #8
    Join Date
    Aug 2009
    Posts
    440

    Re: Variable assigned wrong value?

    That is exactly how the function should operate. The aim of the function is to force any angle, in radians, to fall between -PI and PI. If the angle passed in already meets that criteria, then the function won't return a different value. While I debugged the function, I noticed that my temp variable in the function is not being assigned the value I expected. What is happening, is that the correct value is going into a register, and then the assembly code uses that register for the comparisons. According to the assembly and registers, that function is returning the correct value.

    The problem I am seeing, however, is that the correct value is put into the return register. Then, for some reason, we convert that value (which is a float) from an integer to a float. So, it looks like the assembly is getting confused and thinks the functions return value is an integer:

    Code:
       N:807160F6 F742F2EB  BL       restrictAngle 
       N:807160FA EE000A10  VMOV     s0,r0
       N:807160FE EEB80AC0  VCVT.F32.S32 s0,s0
       N:80716102 ED8D0A00  VSTR     s0,[sp,#0]
       N:80716106     E003  B        0x80716110
    This is the assembly code for when the function is called and storing that value. Above, r0 holds the return value for restrictAngle. That value is moved into s0, and then we proceed to do some conversion, VCVT.F32.S32, on that value.

    Again, for my this project, we are using the ARM compiler. I am not seeing this when I use GCC or Microsoft's compiler.

    Before that conversion call, s0 holds the correct value. After that conversion, s0 holds 1.0617528e+009. I hope this helps clarify what I am seeing.

  9. #9
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Variable assigned wrong value?

    Quote Originally Posted by Alterah View Post
    The problem I am seeing, however, is that the correct value is put into the return register. Then, for some reason, we convert that value (which is a float) from an integer to a float. So, it looks like the assembly is getting confused and thinks the functions return value is an integer:
    OK, is the original program a 'C' program (not C++)? If it is, there is an explanation. If the 'C' function is not prototyped before use, 'C' assumes the function will return an int.

    Regards,

    Paul McKenzie

  10. #10
    Join Date
    Aug 2009
    Posts
    440

    Re: Variable assigned wrong value?

    The original program is a mixture of C and C++ code. However, all of this is happening in .c files. I do want to point out that the restrictAngle function is in a declared in a different file, and defined in yet a different file. In order for the file that we are calling this function to use the function, we have to include the header where the declaration lives. So, I would have to say that this function is definitely declared before we use it.
    Last edited by Alterah; November 16th, 2012 at 12:36 PM.

  11. #11
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Variable assigned wrong value?

    Quote Originally Posted by Alterah View Post
    The original program is a mixture of C and C++ code. However, all of this is happening in .c files.
    Well, it's time to review the rules of 'C' carefully.

    Since the files are 'C', and the files are indeed compiled using the rules of 'C', then all bets are off if you did not prototype your functions that return float.

    Here is an example:
    Code:
    int main()
    {
        double x = sin(0.3);
    }
    This seems to be OK, and it will compile for 'C' (not for C++). And there lies the whole issue, and that is that 'C' compiles this just fine, but C++ doesn't (which is also the reason why prototypes were introduced to 'C' later on after the original 'C' specification -- too many bugs due to functions being called with wrong arguments and wrong return types).

    The 'C' program above will do exactly as you've explained. The reason is that 'C' assumes that sin() returns an int, not a double since the sin() function wasn't previously prototyped. Here is the correction:
    Code:
    #include <math.h>
    int main()
    {
        double x = sin(0.3);
    }
    This now returns a double, since the math.h header has the sin() function prototyped.

    So you need to go over your 'C' modules, and see if all of your functions have been prototyped. Again, 'C' doesn't give you a compiler error when you do not prototype your functions, instead 'C' assumes int and will force the function to return an int.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; November 16th, 2012 at 12:41 PM.

  12. #12
    Join Date
    Aug 2009
    Posts
    440

    Re: Variable assigned wrong value?

    Ok. I checked the prototype for this function. All looks good there. If for some reason the header file is not included in the file that we call the function, can C and the linker still somehow find the definition for this function and compile and link fine?

    Edit: That appears to be what happened. I never actually checked this file to see if it included the header file with the prototype. Our build system wound up finding the object with the function definition and linked that. After including the correct header file, everything appears to be working. Thank you Paul. You've been a huge help. I've also learned something about C I never knew.
    Last edited by Alterah; November 16th, 2012 at 01:14 PM.

  13. #13
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Variable assigned wrong value?

    Quote Originally Posted by Alterah View Post
    If for some reason the header file is not included in the file that we call the function, can C and the linker still somehow find the definition for this function and compile and link fine?
    It will compile and link "fine", as far as 'C' is concerned. That's the problem.

    If you don't tell 'C' about the functions you're calling by prototyping them, nothing can coerce the compiler to do anything except assume the function returns an int. Without a prototype, you can put all sorts of code that suggests that the function returns a double or float, but that isn't going to help you. For 'C', you must tell the 'C' compiler up front the exact prototype of your functions.

    Yes, the linker will find the function, and that again becomes a problem. The original simple program I posted without the header produces undefined behaviour. Since the sin() function actually returns a double, but the compiler assumes it returns an int, who knows what condition the stack will be on return. Maybe the stack is so messed up, the program may crash.
    Edit: That appears to be what happened. I never actually checked this file to see if it included the header file with the prototype. Our build system wound up finding the object with the function definition and linked that. After including the correct header file, everything appears to be working. Thank you Paul. You've been a huge help. I've also learned something about C I never knew.
    No problem.

    Regards,

    Paul McKenzie

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured