return local variable

This is a discussion on return local variable within the C Programming forums, part of the General Programming Boards category; It is said that, you should not return value that is created on stack. i.e the auto variable or the ...

  1. #1
    Registered User
    Join Date
    Oct 2004
    Posts
    21

    return local variable

    It is said that, you should not return value that is created on stack. i.e the auto variable or the local variables. Can anyone tell me how the program below prints the right value "hi"???
    char* foo() {
    char x[10] ;
    strcpy( x, "hi");
    return x;
    }
    int main(){
    char *f;
    f = foo();
    printf( "%s", f);
    }


    Sorry that my code isn't tagged but I'm in too big a hurry to read << !! Posting Code? Read this First !! >>
    Last edited by Salem; 10-21-2004 at 01:18 PM. Reason: Added a RED MESSAGE

  2. #2
    Registered User Scribbler's Avatar
    Join Date
    Sep 2004
    Location
    Aurora CO
    Posts
    266
    Code:
    f = foo();
    is expecting a pointer to type char to be returned. And while an array name without a subscript is technically the address of the array, it needs to be dereferenced to be returned.

    Code:
    #include <stdio.h>
    
    char * foo(void);
    
    int main()
    {
        char *f;
        
        f = foo();
        printf( "%s", f);
    
        return 0;
    }
    
    char * foo(void) 
    {
        char *x;
        strcpy( x, "hi");
        
        return x;
    }
    Last edited by Scribbler; 10-21-2004 at 04:00 AM.

  3. #3
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,264
    Uh, Scribbler... that code you posted is very wrong.

    Can anyone tell me how the program below prints the right value "hi"???
    It prints the right value because the memory hasn't been overwritten yet. Basically, you are just getting lucky.

  4. #4
    Registered User
    Join Date
    Oct 2004
    Posts
    21
    Hey, I am not understanding what you are trying to do in the function foo you wrote
    You got the syntax right. But in foo, you have created a character pointer that points no where and copied "hi" to it. This should result in run-time error.
    Well, if you allocate memory at runtime on heap and return the pointer, then foo returns pointer to vaild data. Check the program below:
    #include <stdio.h>

    char * foo(void);

    int main()
    {
    char *f;

    f = foo();
    printf( "%s", f);

    return 0;
    }

    char * foo(void)
    {
    char *x;
    x = (char*) malloc( sizeof(char)*10);

    strcpy( x, "hi");

    return x;
    }
    But, if you create character array on stack i.e create a local variable of foo and return it as shown below :
    #include <stdio.h>

    char * foo(void);

    int main()
    {
    char *f;

    f = foo();
    printf( "%s", f);

    return 0;
    }

    char * foo(void)
    {
    char x[10];
    strcpy( x, "hi");

    return x;
    }
    x should theoritical point to data the cease to exist after function foo returns. But, actually f in main points to the valid data "hi". How is that possible. Why was that not overwritten when the function foo returned??

  5. #5
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,264
    Why was that not overwritten when the function foo returned??
    Because you didnt overwrite it. Think about the situation for a minute:

    the x array is allocated on the stack. Once the function returns, the stack pointer moves beyond the scope of where x was located. This means that once you allocate more memory on the stack, the memory where x is will be overwritten.

    Look at the following:

    Code:
    #include <stdio.h>
    #include <string.h>
    
    char* foo() {
    	char x[10] ;
    	strcpy( x, "hi");
    	return x;
    }
    
    void overwriteStack()
    {
    	char x[10];
    }
    
    int main(){
    	char *f;
    	f = foo();
    	overwriteStack();
    	printf( "%s\n", f);
    	return 0;
    }
    You should now see that "hi" will not be printed.

  6. #6
    Registered User
    Join Date
    Mar 2003
    Posts
    143
    It just so happens that this works for your compiler in this particular case. The array x is only valid in the function where it is declared. The fact that the memory locationstill happens to be set to "hi" after the function returns is simply because the computer hasn't had the need to overwrite it yet - but that is not guaranteed. The best way to pass a string out of a function is like this:
    Code:
    void foo(char f[]) 
    {
      strcpy( f, "hi");
    }
    
    int main(void)
    {
      char f[10];
      foo(f);
      printf( "%s", f);
    
      return 0;
    }
    An alternative way is this:
    Code:
    char* foo() 
    {
      char * x = malloc(10*sizeof(*x)) ;
      strcpy( x, "hi");
      return x;
    }
    
    int main(void)
    {
      char *f;
      f = foo();
      printf( "%s", f);
    
      free(f);
    
      return 0;
    }
    But (in my opinion) the 2nd way is dangerous because you are malloc()ing and free()ing in different functions and could forget for one branch of the code leading to memory leaks. Go with the 1st way.

    Scribbler: your foo() function writes to a random, unallocated memory location - that is a memory leak.

    edit:: must learn to type faster...
    DavT
    -----------------------------------------------

  7. #7
    Registered User
    Join Date
    Oct 2004
    Posts
    21
    That makes sense. thanks.

  8. #8
    Registered User
    Join Date
    Oct 2004
    Posts
    21
    hey, I tried the same program with an additional int definition in the function foo. Now the data is getting corupted. Why is that?

    #include <stdio.h>

    char * foo(void);

    int main()
    {
    char *f;

    f = foo();
    printf( "%s", f);

    return 0;
    }

    char * foo(void)
    {
    int i=10;char x[10];
    strcpy( x, "hi");

    return x;
    }

  9. #9
    Registered User
    Join Date
    Mar 2003
    Posts
    143
    hey, I tried the same program with an additional int definition in the function foo. Now the data is getting corupted. Why is that?
    This is exactly why this is bad code. It only worked before because of a fluke in the way the compiler works. The moral of the story - write code properly.
    DavT
    -----------------------------------------------

  10. #10
    Registered User
    Join Date
    Oct 2004
    Posts
    21
    I understand that. I only want to know why an additional variable will overwrite the next variable in the stack??

  11. #11
    not-a-geek
    Join Date
    Apr 2004
    Posts
    210
    Quote Originally Posted by sangi
    I understand that. I only want to know why an additional variable will overwrite the next variable in the stack??
    It has nothing to do with that variable. The code you wrote has an undefined behaviour in C. That's it. It now all depends on how the generated code looks like.
    I.e. your first piece of code did not work on my system at all. It printed lots of garbage. After compiling it again with different optimization model, the code "worked". Your second example works for me too - but again only on that specific optimization level.

    If you, for whatever reason, really want to know why it works without that integer but not with it, you will need to tell your compiler to generate an object as assembler output instead of a binary version. Or even better, run the programm with a debugger that can step through assembler code like ddd. I guess MS Visual Cxx can do the same. Then see what the value of %eax is when foo() returns and monitor the data at that location in memory while stepping through the code. You might also want to use a string longer than "hi" because any serious compiler will optimize that to an integer constant which might or might not make things harder for you.
    main() { int O[!0<<~-!0]; (!0<<!0)[O]+= ~0 +~(!0|!0<<!0); printf("a function calling "); }

  12. #12
    Registered User Scribbler's Avatar
    Join Date
    Sep 2004
    Location
    Aurora CO
    Posts
    266
    Oh I'm fully aware that the code I left was total fud. I merely tweaked the original code to show 'how' to pass that information back. If you wanted it a bit more reliable I woulda written like this
    Code:
    #include <stdio.h>
    
    char *foo();
    
    int main()
    {
        
        char *f;
        
        f = foo();
        printf( "%s", f);
    
        return 0;
    }
    
    char *foo() 
    {
        static char x[] = "goodbye";
        strcpy( x, "hi");
        
        return x;
    }
    Which would make x a static variable, which doesn't die upon function completion.
    Last edited by Scribbler; 10-21-2004 at 12:27 PM.

  13. #13
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,264
    Now the data is getting corupted. Why is that?
    Your compiler must be generating code that is corrupting the stack (Im not sure why though). On my computer, the word "hi" is still printed just fine.

    If you want to get a better idea of what is happening, then I suggest you get yourself a good debugger. This will allow you to step through each line of code, and view what the stack looks like and how it changes.

  14. #14
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,175
    Think of the stack as a pile of dishes. When you call a function, you put a piece of paper on top of the stack and then put a plate on the pile for each argument you pass to the function and each automatic variable defined inside the function. So the piece of paper in the pile of plates marks how big the stack was before the function was called. Then you can do whatever you want with the plates that are on top of the piece of paper when you're inside the function. When the function exits, all the plates on top of the piece of paper are taken away and discarded. This is where your string is that you're trying to return. You're returning a pointer to a plate that's been taken away. If another function is called or something else causes the pile of plates to grow as high as the point where your string was, it will overwrite whatever was at that memory location. Once a plate is taken away from the stack, you should never try referencing it again.

    What I wouldn't give for a whiteboard.
    If you understand what you're doing, you're not learning anything.

  15. #15
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Why in the hell are you people helping this person? They have blatently stated that they "don't have the time to read how to use code tags". Yet, they had enough time to post multiple posts containing code, in hopes that YOU will take the time to read their unformatted crap, and fix their problem.

    Here's a better idea: When people are too lazy to use code tags, EVERYONE that reads their post mark them down. Support the "Big red squares for stupid people." initiative.

    Quzah.
    Hope is the first step on the road to disappointment.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How can I make this code more elegant?
    By ejohns85 in forum C++ Programming
    Replies: 3
    Last Post: 04-02-2009, 09:55 AM
  2. 6 measly errors
    By beene in forum Game Programming
    Replies: 11
    Last Post: 11-14-2006, 11:06 AM
  3. Why only 32x32? (OpenGL) [Please help]
    By Queatrix in forum Game Programming
    Replies: 2
    Last Post: 01-23-2006, 02:39 PM
  4. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 04:00 PM
  5. Variable Allocation in a simple operating system
    By awkeller in forum C Programming
    Replies: 1
    Last Post: 12-08-2001, 02:26 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21