CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 2 of 2 FirstFirst 12
Results 16 to 25 of 25
  1. #16
    Join Date
    Oct 2006
    Location
    Sweden
    Posts
    3,654

    Re: problem with global variables in Visual Studio 2010

    John, as far as i know today most (all?) compilers extends every param to printf to int size (at least, I don't know how it's done in 64 bit code). I know I have read about why it's done like that somewhere but neither remember where or why...

    To ensure that my memory was correct I checked the output from VC2005 and this is what I got in debug
    Code:
      int a = 1;
    004117BE  mov         dword ptr [a],1 
      char b = 'a';
    004117C5  mov         byte ptr [b],61h 
      printf( "%d%c\n", a, b );
    004117C9  movsx       eax,byte ptr [b] 
    004117CD  mov         esi,esp 
    004117CF  push        eax  
    004117D0  mov         ecx,dword ptr [a] 
    004117D3  push        ecx  
    004117D4  push        offset string "%d%c\n" (415810h) 
    004117D9  call        dword ptr [__imp__printf (4182B4h)]
    and in release
    Code:
      int a = 1;
      char b = 'a';
      printf( "%d%c\n", a, b );
    00401000  push        61h  
    00401002  push        1    
    00401004  push        offset string "%d%c\n" (402104h) 
    00401009  call        dword ptr [__imp__printf (4020A0h)]
    Anyway, unless this behaviour is defined by the standard we shouldn't rely on it of course.
    Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are, by
    definition, not smart enough to debug it.
    - Brian W. Kernighan

    To enhance your chance's of getting an answer be sure to read
    http://www.codeguru.com/forum/announ...nouncementid=6
    and http://www.codeguru.com/forum/showthread.php?t=366302 before posting

    Refresh your memory on formatting tags here
    http://www.codeguru.com/forum/misc.php?do=bbcode

    Get your free MS compiler here
    https://visualstudio.microsoft.com/vs

  2. #17
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: problem with global variables in Visual Studio 2010

    Quote Originally Posted by S_M_A View Post
    John, as far as i know today most (all?) compilers extends every param to printf to int size.
    Not true.

    What you are referring to is not "expansion" but is called integer promotion. This rule states that all integer types with a sizeof smaller than int get promoted to int when used as a vararg.
    it says nothing about non-integer types. a pointer remains a pointer (of whatever size you're compiling at), floating points remain floats, doubles and long doubles. and 64bit ints remain as 64bit ints (they are not demoted to 32bit ints).

    on 64bit compiles, results vary depending on your compiler. if an int is a 64bit then promotion results in 64bit ints. if int is 32bit then promotion is 32bit. Don't assume that 'int' is either 32 or 64bit, it doesn't even have to be either of those (I have a compiler where int is a 80bit).
    Last edited by OReubens; August 27th, 2012 at 11:15 AM.

  3. #18
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    Re: problem with global variables in Visual Studio 2010

    What would be really interesting would be to know what happens if you specify an int as one of the arguments but then you actually pass a float. There's something in the back of my mind that passing the wrong type of parameter can be just as disastrous as passing the wrong number of parameters. I think the compiler carries out very little in the way of parameter validation. In fact, could it do anything more than very basic validation when the format specifier is only a string?
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  4. #19
    Join Date
    May 2009
    Posts
    2,413

    Re: problem with global variables in Visual Studio 2010

    Quote Originally Posted by D_Drmmr View Post
    Strictly speaking that's not a singleton, because it's possible to create multiple instances of the class.
    Also, I would advice against trying to fix a problem that is not understood. If the actual cause of the problem is some memory corruption, then using a singleton won't fix anything.
    Strictly speaking yes and I was going to come back to that. The main purpose of my post was to make the OP try something very defined which could then be the basis for further suggestions depending on the result. But since the OP has lost interest and abandoned the thread I see no reason to put in any more effort into this.

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

    Re: problem with global variables in Visual Studio 2010

    Quote Originally Posted by John E View Post
    I think the compiler carries out very little in the way of parameter validation.
    How about "no validation". It's all in your hands, which is why printf() is dangerous.

    Regards,

    Paul McKenzie

  6. #21
    Join Date
    Oct 2006
    Location
    Sweden
    Posts
    3,654

    Re: problem with global variables in Visual Studio 2010

    Some compiler parse the format string and give warnings if the parameters fail (think gcc does that).

    It might be the reason (and probably is) OReubens but when did that change? Just as John I also remember (at least think I do) that it hasn't always been like that. On the other hand it might also be that those compilers weren't compliant?

    Edit: Yepp, OReubens is correct. This is what's stated in ISO/IEC 9899:2011 (C)
    6.5.2.2 Function calls

    6 If the expression that denotes the called function has a type that does not include a
    prototype, the integer promotions are performed on each argument, and arguments that
    have type float are promoted to double. These are called the default argument
    promotions.

    7 If the expression that denotes the called function has a type that does include a prototype,
    the arguments are implicitly converted, as if by assignment, to the types of the
    corresponding parameters, taking the type of each parameter to be the unqualified version
    of its declared type. The ellipsis notation in a function prototype declarator causes
    argument type conversion to stop after the last declared parameter. The default argument
    promotions are performed on trailing arguments.
    The ISO/IEC 14882:2011 (C++) says of course pretty much the same
    Last edited by S_M_A; August 27th, 2012 at 01:53 PM.
    Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are, by
    definition, not smart enough to debug it.
    - Brian W. Kernighan

    To enhance your chance's of getting an answer be sure to read
    http://www.codeguru.com/forum/announ...nouncementid=6
    and http://www.codeguru.com/forum/showthread.php?t=366302 before posting

    Refresh your memory on formatting tags here
    http://www.codeguru.com/forum/misc.php?do=bbcode

    Get your free MS compiler here
    https://visualstudio.microsoft.com/vs

  7. #22
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: problem with global variables in Visual Studio 2010

    Quote Originally Posted by John E View Post
    What would be really interesting would be to know what happens if you specify an int as one of the arguments but then you actually pass a float. There's something in the back of my mind that passing the wrong type of parameter can be just as disastrous as passing the wrong number of parameters. I think the compiler carries out very little in the way of parameter validation. In fact, could it do anything more than very basic validation when the format specifier is only a string?
    Quote Originally Posted by S_M_A View Post
    Some compiler parse the format string and give warnings if the parameters fail (think gcc does that).

    It might be the reason (and probably is) OReubens but when did that change? Just as John I also remember (at least think I do) that it hasn't always been like that. On the other hand it might also be that those compilers weren't compliant?

    Edit: Yepp, OReubens is correct. This is what's stated in ISO/IEC 9899:2011 (C)The ISO/IEC 14882:2011 (C++) says of course pretty much the same

    What happens has always been the same on pretty much any C/C++ compiler that works with the common stack-based principle for passing variables (not all compilers do). the c/c++ spec is quite clear on it.

    Code:
    printf("something something", myInt, myFloat, myDouble, myInt64, myChar, myShort, &myInt, "something else");
    it pushes all the parameters on that stack.
    a pointer (or literal string which is a pointer to that literal strign stored elsewhere) will get pushed as a 32bit value (64bit value when compiling for 64bit, but again, it could be anything)
    myInt is an int so is pushed as is (whatever size an int is for that compiler, could be anything, the only guarantee the C spec gives you is that it is at least 16bit, there is no upper limit constraint).
    myFloat will be promoted to a double, so 8 bytes are pushed on the stack
    myDouble will be pushed as a double so 8 bytes are pushed on the stack
    myInt64 is an 64bit int. if 'int' on your machine is less or equal to 64bit, it will be pushed as an int64 so 8 bytes are pushed on the stack, if it is less than the sizeof(int), it will be promoted to an int. and whatever number of bytes are in an int will be pushed.
    myChar gets promoted to int, and sizeof(int) bytes are pushed on the stack.
    &myInt and the literal strings are both pointers and get pushed on the stack at whatever size a pointer is.

    The above code will compile and run perfectly without any problem !!! There will be no leaks or errors of any kind.
    Why not ? because there are no format specifications.


    When you use format specifications in the (first) string, you are effectively TELLING the compiler how it should interpret the bunch of bytes (whatever they may be) should be interpreted. If you fail to properly match up the format specifiers with the actual vararg parameters, things can go bad, and go horribly bad even. But it's equally possible that nothing goes wrong other than gettign a formatted string that has unexpected content.

    %d, %u specifiers will usually only lead to incorrect values in the resultant string (assuming the resultant string is still smaller than the output buffer).
    a %s could cause a crash, because it'll take whatever value is on the stack, cast it to a pointer and dereference the pointer, if that pointer is invalid.... OOPS.
    %f can also cause weird effects depending on how robust the IEEE handling is. (and some are bad).


    the above is why c++ streams are better than printf. because they ensure the types you pass are handled correctly, rather than hoping the programmer matched the format specifiers up correctly with the passed arguments.
    Last edited by OReubens; August 28th, 2012 at 04:43 AM.

  8. #23
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    Re: problem with global variables in Visual Studio 2010

    Hi OReubens. My question was about a more subtle problem... what happens if the format specifier specifies type int but the passed parameter is actually (say) a float?
    "A problem well stated is a problem half solved.” - Charles F. Kettering

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

    Re: problem with global variables in Visual Studio 2010

    Quote Originally Posted by John E View Post
    Hi OReubens. My question was about a more subtle problem... what happens if the format specifier specifies type int but the passed parameter is actually (say) a float?
    The behaviour is undefined.

    Regards,

    Paul McKenzie

  10. #25
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: problem with global variables in Visual Studio 2010

    Code:
    printf("%d", myFloat);
    promotes the float to a double
    a double gets pushed on the stack (usually 8 bytes)
    printf sees the %d and interprets the bits on the stack as being an int and formats it as such. the result is semi predictable assuming you know the format/size of the doubles and the format/size of the ints for that computer. most doubles use IEEE, but again, there are compilers that do it differently.

    It will essentially do the same as:
    Code:
    float myFloat = 3.14; // Hmmmm pie.
    double tmpDouble = myFloat;
    char buffer[100];
    itoa( *(int*)&tmpDouble, buffer, 10 );
    You're just telling the compiler to interpret the bits of the float as being an int. results are.. undefined in general, though very defined on a specific platform.

Page 2 of 2 FirstFirst 12

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