linux-c-programming.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* pass a local variable to a function
@ 2009-03-25 16:21 明亮
  2009-03-25 17:17 ` Lorenzo Beretta
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: 明亮 @ 2009-03-25 16:21 UTC (permalink / raw)
  To: linux-c-programming

Hi guys,

This is my first email in this list, any help is much appreciated.
As I know, it's not allowed to pass a local variable to a function,
because the stack where local variable resides will be reused by other
functions.
eg:
     1  #include <stdio.h>
     2
     3  char *fetch();
     4
     5  int main(int argc, char *argv[]){
     6          char *string;
     7          string = fetch();
     8          printf("%s\n", string);
     9          exit(0);
    10  }
    11
    12  char *fetch(){
    13          char string[10];
    14          scanf("%s", string);
    15          return string;
    16  }

When the application is executed, after input "a", it will produce
unknown characters, like "8Šè¿ôÿO". Which is like what I expect

However, if I change line 13 to:
    13           char string[1024];

When I type "a", it echos "a", which is out of my expectation

Why does it behave like this?

Thanks in advance,
longapple
--
To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: pass a local variable to a function
  2009-03-25 16:21 pass a local variable to a function 明亮
@ 2009-03-25 17:17 ` Lorenzo Beretta
  2009-03-26 13:09   ` Mingliang
  2009-03-25 18:50 ` Bert Wesarg
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 6+ messages in thread
From: Lorenzo Beretta @ 2009-03-25 17:17 UTC (permalink / raw)
  To: linux-c-programming

明亮 ha scritto:
> Hi guys,
> 
> This is my first email in this list, any help is much appreciated.
> As I know, it's not allowed to pass a local variable to a function,
> because the stack where local variable resides will be reused by other
> functions.
> eg:
>      1  #include <stdio.h>
>      2
>      3  char *fetch();
>      4
>      5  int main(int argc, char *argv[]){
>      6          char *string;
>      7          string = fetch();
>      8          printf("%s\n", string);
>      9          exit(0);
>     10  }
>     11
>     12  char *fetch(){
>     13          char string[10];
>     14          scanf("%s", string);
>     15          return string;
>     16  }
> 
> When the application is executed, after input "a", it will produce
> unknown characters, like "8Šè¿ôÿO". Which is like what I expect
> 
> However, if I change line 13 to:
>     13           char string[1024];
> 
> When I type "a", it echos "a", which is out of my expectation
> 
> Why does it behave like this?
> 
> Thanks in advance,
> longapple
> --
> To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

Try something like this
------
void p(int n){
	int onstack;
	printf("%p\n", &onstack);
	if(n>0) p(n-1);
}

int main(){
	p(5);
	return 0;
}
------

It should (system dependant) print a sequence of decreasing hex numbers;
that's because each time you call a function on your computer, the local 
stack grows downwards.

When you scanf() into a character array, it writes into the first 
characters of your array, that is string[0], then string[1], and so on: 
notice that the address of string[1] is GREATER than the address of 
string[0]...

Summing up there are two cases (assume that X stands for "any value"):

1) string[10]
==> { X, X, X, X, X, X, X, X, '\0', 'a' }
2) string[1024]
==> { X, X, X, (long sequence of garbage)..., '\0', a' }

When you call printf(), the printf function overwrites some bytes for 
its own stack variables: if it takes more than 10 bytes (eg 42), the 
small array will be completely overwritten, while with the big array it 
will only overwrite string[1023...980] (which was garbage anyway!), 
leaving string[0...979] intact.

I hope that was helpful; try gooling "buffer overflow" for more info


lb

--
To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: pass a local variable to a function
  2009-03-25 16:21 pass a local variable to a function 明亮
  2009-03-25 17:17 ` Lorenzo Beretta
@ 2009-03-25 18:50 ` Bert Wesarg
  2009-03-26  8:42 ` Glynn Clements
  2009-03-26  9:49 ` Jon Mayo
  3 siblings, 0 replies; 6+ messages in thread
From: Bert Wesarg @ 2009-03-25 18:50 UTC (permalink / raw)
  To: 明亮; +Cc: linux-c-programming

On Wed, Mar 25, 2009 at 17:21, 明亮 <longapple@gmail.com> wrote:
> Hi guys,
>
> This is my first email in this list, any help is much appreciated.
> As I know, it's not allowed to pass a local variable to a function,
> because the stack where local variable resides will be reused by other
> functions.
> eg:
>      1  #include <stdio.h>
>      2
>      3  char *fetch();
>      4
>      5  int main(int argc, char *argv[]){
>      6          char *string;
>      7          string = fetch();
>      8          printf("%s\n", string);
>      9          exit(0);
>     10  }
>     11
>     12  char *fetch(){
>     13          char string[10];
>     14          scanf("%s", string);
>     15          return string;
>     16  }
>
> When the application is executed, after input "a", it will produce
> unknown characters, like "8Šè¿ôÿO". Which is like what I expect
>
> However, if I change line 13 to:
>     13           char string[1024];
>
> When I type "a", it echos "a", which is out of my expectation
>
> Why does it behave like this?
That is irrelevant. What you try to do is 'undefined behavior', so you
should have no expectations, whether it works for you or not.

Bert
>
> Thanks in advance,
> longapple

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: pass a local variable to a function
  2009-03-25 16:21 pass a local variable to a function 明亮
  2009-03-25 17:17 ` Lorenzo Beretta
  2009-03-25 18:50 ` Bert Wesarg
@ 2009-03-26  8:42 ` Glynn Clements
  2009-03-26  9:49 ` Jon Mayo
  3 siblings, 0 replies; 6+ messages in thread
From: Glynn Clements @ 2009-03-26  8:42 UTC (permalink / raw)
  To: 明亮; +Cc: linux-c-programming


明亮 wrote:

> This is my first email in this list, any help is much appreciated.
> As I know, it's not allowed to pass a local variable to a function,
> because the stack where local variable resides will be reused by other
> functions.

It's perfectly acceptable to pass a local variable to or from a
function. It's also acceptable to pass the address of a local variable
to a function.

What isn't acceptable is returning the address of a local variable
from a function, as the variable will cease to exist once the function
returns.

> eg:
>      1  #include <stdio.h>
>      2
>      3  char *fetch();
>      4
>      5  int main(int argc, char *argv[]){
>      6          char *string;
>      7          string = fetch();
>      8          printf("%s\n", string);
>      9          exit(0);
>     10  }
>     11
>     12  char *fetch(){
>     13          char string[10];
>     14          scanf("%s", string);
>     15          return string;

This returns the address of the local variable "string", which isn't
valid.

>     16  }
> 
> When the application is executed, after input "a", it will produce
> unknown characters, like "8�è¿ôÿO". Which is like what I expect
> 
> However, if I change line 13 to:
>     13           char string[1024];
> 
> When I type "a", it echos "a", which is out of my expectation
> 
> Why does it behave like this?

Making the array larger means that the start address is further down
the stack (most common architectures use a descending stack). The
printf() call is presumably using less than 1K of stack, so it doesn't
overwrite the variable.

This won't work if the platform uses an ascending stack, or if it
returns unused stack memory to the OS, or if printf() uses more than
1K for local variables (directly or indirectly), or if the
architecture handles signals, interrupts, etc using the same stack as
the main thread. There are other possible reasons why it may fail.

If you want to understand the internals of program execution, learn
assembly language and examine the disassembled code.

-- 
Glynn Clements <glynn@gclements.plus.com>
--
To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: pass a local variable to a function
  2009-03-25 16:21 pass a local variable to a function 明亮
                   ` (2 preceding siblings ...)
  2009-03-26  8:42 ` Glynn Clements
@ 2009-03-26  9:49 ` Jon Mayo
  3 siblings, 0 replies; 6+ messages in thread
From: Jon Mayo @ 2009-03-26  9:49 UTC (permalink / raw)
  To: 明亮; +Cc: linux-c-programming

On Wed, Mar 25, 2009 at 9:21 AM, 明亮 <longapple@gmail.com> wrote:
> Hi guys,
>
> This is my first email in this list, any help is much appreciated.
> As I know, it's not allowed to pass a local variable to a function,
> because the stack where local variable resides will be reused by other
> functions.
> eg:
>      1  #include <stdio.h>
>      2
>      3  char *fetch();
>      4
>      5  int main(int argc, char *argv[]){
>      6          char *string;
>      7          string = fetch();
>      8          printf("%s\n", string);
>      9          exit(0);
>     10  }
>     11
>     12  char *fetch(){
>     13          char string[10];
>     14          scanf("%s", string);
>     15          return string;
>     16  }
>
> When the application is executed, after input "a", it will produce
> unknown characters, like "8Šè¿ôÿO". Which is like what I expect
>
> However, if I change line 13 to:
>     13           char string[1024];
>
> When I type "a", it echos "a", which is out of my expectation
>
> Why does it behave like this?
>
> Thanks in advance,
> longapple

The data for string[] is being destroyed by the call to printf (first
thing you call after fetch). On your particular system making it 1024
puts it out of reach of printf's call frame. your stack is probably
growing downwards, so the call frame of printf is ending up near the
end of what string[] used to be. If you fill your string[] with memset
of 'a' and leave not null terminated, you can easily see the point
where your data ends and the next function starts to clobber you.

-- 
Jon Mayo
<jon.mayo@gmail.com>
--
To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: pass a local variable to a function
  2009-03-25 17:17 ` Lorenzo Beretta
@ 2009-03-26 13:09   ` Mingliang
  0 siblings, 0 replies; 6+ messages in thread
From: Mingliang @ 2009-03-26 13:09 UTC (permalink / raw)
  To: Lorenzo Beretta; +Cc: linux-c-programming

Wow!!! learned a lot!!!. Thanks!!!
-Mingliang

On Wed, Mar 25, 2009 at 9:17 AM, Lorenzo Beretta <lory.fulgi@infinito.it> wrote:
> 明亮 ha scritto:
>>
>> Hi guys,
>>
>> This is my first email in this list, any help is much appreciated.
>> As I know, it's not allowed to pass a local variable to a function,
>> because the stack where local variable resides will be reused by other
>> functions.
>> eg:
>>     1  #include <stdio.h>
>>     2
>>     3  char *fetch();
>>     4
>>     5  int main(int argc, char *argv[]){
>>     6          char *string;
>>     7          string = fetch();
>>     8          printf("%s\n", string);
>>     9          exit(0);
>>    10  }
>>    11
>>    12  char *fetch(){
>>    13          char string[10];
>>    14          scanf("%s", string);
>>    15          return string;
>>    16  }
>>
>> When the application is executed, after input "a", it will produce
>> unknown characters, like "8Šè¿ôÿO". Which is like what I expect
>>
>> However, if I change line 13 to:
>>    13           char string[1024];
>>
>> When I type "a", it echos "a", which is out of my expectation
>>
>> Why does it behave like this?
>>
>> Thanks in advance,
>> longapple
>> --
>> To unsubscribe from this list: send the line "unsubscribe
>> linux-c-programming" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>
> Try something like this
> ------
> void p(int n){
>        int onstack;
>        printf("%p\n", &onstack);
>        if(n>0) p(n-1);
> }
>
> int main(){
>        p(5);
>        return 0;
> }
> ------
>
> It should (system dependant) print a sequence of decreasing hex numbers;
> that's because each time you call a function on your computer, the local
> stack grows downwards.
>
> When you scanf() into a character array, it writes into the first characters
> of your array, that is string[0], then string[1], and so on: notice that the
> address of string[1] is GREATER than the address of string[0]...
>
> Summing up there are two cases (assume that X stands for "any value"):
>
> 1) string[10]
> ==> { X, X, X, X, X, X, X, X, '\0', 'a' }
> 2) string[1024]
> ==> { X, X, X, (long sequence of garbage)..., '\0', a' }
>
> When you call printf(), the printf function overwrites some bytes for its
> own stack variables: if it takes more than 10 bytes (eg 42), the small array
> will be completely overwritten, while with the big array it will only
> overwrite string[1023...980] (which was garbage anyway!), leaving
> string[0...979] intact.
>
> I hope that was helpful; try gooling "buffer overflow" for more info
>
>
> lb
>
> --
> To unsubscribe from this list: send the line "unsubscribe
> linux-c-programming" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2009-03-26 13:09 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-03-25 16:21 pass a local variable to a function 明亮
2009-03-25 17:17 ` Lorenzo Beretta
2009-03-26 13:09   ` Mingliang
2009-03-25 18:50 ` Bert Wesarg
2009-03-26  8:42 ` Glynn Clements
2009-03-26  9:49 ` Jon Mayo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).