Re: Visual C++ automatically returning a value?

Discussion in 'C Programming' started by Geoff, Dec 11, 2010.

  1. Geoff

    Geoff Guest

    On Sat, 11 Dec 2010 01:19:00 -0800, kevin <> wrote:

    >I'm stumped, and I'd like to elicite opinions from those of you who use
    >Microsoft's Visual C++ 2010. (I routinely use gcc or llvm.)
    >
    >The code below compiles with warning "C4716: 'readLine' : must return a
    >value." (The readLine function is defined to return an int, but does
    >not explicitely return a value. This warning is therefore expected.)
    >gcc and llvm both report similar warning messages about the lack of a
    >return statement.
    >
    >Subsequently executing this program generates the following output:
    >
    >Enter a string: Hello
    >'Hello', length = 5
    >
    >Microsoft states that "an undefined value will be returned when this
    >function is called." Yet, the function is somehow returning a correct
    >value with each run. This is not the case when the program is compiled
    >with gcc or llvm.
    >
    >So, does anyone have an idea about where this mysterious return value
    >is coming from? Why does this function work when it doesn't have a
    >return statement?
    >
    >Thanks-
    >Kevin
    >
    >/********************************************************/
    >#include <stdio.h>
    >
    >int readLine (char buffer[], int max) {
    > char character;
    > int i = 0;
    > int strlength;
    >
    > do {
    > character = getchar ();
    > buffer = character;
    > ++i;
    > } while ( character != '\n' && i < max );
    >
    > buffer[i - 1] = '\0';
    >
    > strlength = i - 1;
    >}
    >
    >int main (void) {
    > char input [10];
    > int length;
    >
    > printf ( "Enter a string: " );
    > length = readLine (input, 10 );
    >
    > printf ( "'%s', length = %i \n", input, length ) ;
    >
    > return 0;
    >}
    >


    You don't have to necessarily build with assembly generation turned on
    to see the code it generates. Breakpoint the function at the strlength
    evaluation and look at the disassembly window:

    This is the end of your readLine function in debug mode on x86.

    strlength = i - 1;
    01141406 mov eax,dword ptr
    01141409 sub eax,1
    0114140C mov dword ptr [strlength],eax
    }
    0114140F pop edi
    01141410 pop esi
    01141411 pop ebx
    01141412 add esp,0E4h
    01141418 cmp ebp,esp
    0114141A call @ILT+300(__RTC_CheckEsp) (1141131h)
    0114141F mov esp,ebp
    01141421 pop ebp
    01141422 ret

    .... and this is the call-return code in main.

    01141495 call @ILT+215(_readLine) (11410DCh)
    0114149A add esp,8
    0114149D mov dword ptr [ebp-20h],eax


    It's easy to see that the remnant EAX is passed back to main as the
    return value. This is an artifact of the compiler and if you had done
    any calculation after evaluating strlength EAX would contain a
    different value and the function would fail.

    It also fails big-time in release mode, returning garbage.

    I guess this is a good argument for paying attention to warnings like
    this and properly returning values when the compiler tells you to.
     
    Geoff, Dec 11, 2010
    #1
    1. Advertising

  2. Geoff

    Geoff Guest

    On Sat, 11 Dec 2010 12:12:24 -0800, Geoff <>
    wrote:

    >On Sat, 11 Dec 2010 01:19:00 -0800, kevin <> wrote:
    >
    >>I'm stumped, and I'd like to elicite opinions from those of you who use
    >>Microsoft's Visual C++ 2010. (I routinely use gcc or llvm.)
    >>
    >>The code below compiles with warning "C4716: 'readLine' : must return a
    >>value." (The readLine function is defined to return an int, but does
    >>not explicitely return a value. This warning is therefore expected.)
    >>gcc and llvm both report similar warning messages about the lack of a
    >>return statement.
    >>
    >>Subsequently executing this program generates the following output:
    >>
    >>Enter a string: Hello
    >>'Hello', length = 5
    >>
    >>Microsoft states that "an undefined value will be returned when this
    >>function is called." Yet, the function is somehow returning a correct
    >>value with each run. This is not the case when the program is compiled
    >>with gcc or llvm.
    >>
    >>So, does anyone have an idea about where this mysterious return value
    >>is coming from? Why does this function work when it doesn't have a
    >>return statement?
    >>
    >>Thanks-
    >>Kevin
    >>
    >>/********************************************************/
    >>#include <stdio.h>
    >>
    >>int readLine (char buffer[], int max) {
    >> char character;
    >> int i = 0;
    >> int strlength;
    >>
    >> do {
    >> character = getchar ();
    >> buffer = character;
    >> ++i;
    >> } while ( character != '\n' && i < max );
    >>
    >> buffer[i - 1] = '\0';
    >>
    >> strlength = i - 1;
    >>}
    >>
    >>int main (void) {
    >> char input [10];
    >> int length;
    >>
    >> printf ( "Enter a string: " );
    >> length = readLine (input, 10 );
    >>
    >> printf ( "'%s', length = %i \n", input, length ) ;
    >>
    >> return 0;
    >>}
    >>

    >
    >You don't have to necessarily build with assembly generation turned on
    >to see the code it generates. Breakpoint the function at the strlength
    >evaluation and look at the disassembly window:
    >
    >This is the end of your readLine function in debug mode on x86.
    >
    > strlength = i - 1;
    >01141406 mov eax,dword ptr
    >01141409 sub eax,1
    >0114140C mov dword ptr [strlength],eax
    >}
    >0114140F pop edi
    >01141410 pop esi
    >01141411 pop ebx
    >01141412 add esp,0E4h
    >01141418 cmp ebp,esp
    >0114141A call @ILT+300(__RTC_CheckEsp) (1141131h)
    >0114141F mov esp,ebp
    >01141421 pop ebp
    >01141422 ret
    >
    >... and this is the call-return code in main.
    >
    >01141495 call @ILT+215(_readLine) (11410DCh)
    >0114149A add esp,8
    >0114149D mov dword ptr [ebp-20h],eax
    >
    >
    >It's easy to see that the remnant EAX is passed back to main as the
    >return value. This is an artifact of the compiler and if you had done
    >any calculation after evaluating strlength EAX would contain a
    >different value and the function would fail.
    >
    >It also fails big-time in release mode, returning garbage.
    >
    >I guess this is a good argument for paying attention to warnings like
    >this and properly returning values when the compiler tells you to.


    I should add the compiler in release mode does outsmart you by
    inlining readLine and virtually eliminating the call and return by
    rewriting main() as:

    #include <stdio.h>

    int readLine (char buffer[], int max) {
    char character;
    int i = 0;
    int strlength;

    do {
    character = getchar ();
    buffer = character;
    ++i;
    } while ( character != '\n' && i < max );

    buffer[i - 1] = '\0';

    strlength = i - 1;
    }

    int main (void) {
    01351000 push ebp
    01351001 mov ebp,esp
    01351003 sub esp,14h
    01351006 mov eax,dword ptr [___security_cookie (1353000h)]
    0135100B xor eax,ebp
    0135100D mov dword ptr [ebp-4],eax
    01351010 push ebx
    char input [10];
    int length;

    printf ( "Enter a string: " );
    01351011 mov ebx,dword ptr [__imp__printf (13520A4h)]
    01351017 push esi
    01351018 push edi
    01351019 push offset string "Enter a string: " (13520F4h)
    0135101E call ebx
    length = readLine (input, 10 );
    01351020 mov edi,dword ptr [__imp__getchar (135209Ch)]
    01351026 add esp,4
    01351029 xor esi,esi
    0135102B jmp main+30h (1351030h)
    0135102D lea ecx,[ecx]
    01351030 call edi
    01351032 mov byte ptr [ebp+esi-10h],al
    01351036 inc esi
    01351037 cmp al,0Ah
    01351039 je main+40h (1351040h)
    0135103B cmp esi,0Ah
    0135103E jl main+30h (1351030h)

    printf ( "'%s', length = %i \n", input, length ) ;
    01351040 mov eax,dword ptr [ebp-14h]
    01351043 push eax
    01351044 lea ecx,[ebp-10h]
    01351047 push ecx
    01351048 push offset string "'%s', length = %i \n" (1352108h)
    0135104D mov byte ptr [ebp+esi-11h],0
    01351052 call ebx

    return 0;
    }
    01351054 mov ecx,dword ptr [ebp-4]
    01351057 add esp,0Ch
    0135105A pop edi
    0135105B pop esi
    0135105C xor ecx,ebp
    0135105E xor eax,eax
    01351060 pop ebx
    01351061 call __security_check_cookie (135106Ah)
    01351066 mov esp,ebp
    01351068 pop ebp
    01351069 ret


    This is why "it works fine in debug build but doesn't work in release
    build" is typed too many times on planet earth.
     
    Geoff, Dec 11, 2010
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mike
    Replies:
    6
    Views:
    1,884
  2. GS
    Replies:
    1
    Views:
    2,685
    =?Utf-8?B?Q293Ym95IChHcmVnb3J5IEEuIEJlYW1lcikgLSBN
    Jan 19, 2006
  3. orion30
    Replies:
    2
    Views:
    316
    Alf P. Steinbach
    Jul 14, 2003
  4. orion30
    Replies:
    1
    Views:
    301
    Barry Schwarz
    Jul 15, 2003
  5. Replies:
    11
    Views:
    671
    Christos Georgiou
    May 2, 2006
Loading...

Share This Page