LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 01-23-2020, 07:51 PM   #1
barunparichha
Member
 
Registered: Jun 2006
Location: Bangalore,india
Distribution: Linux(Redhat,fedora,suse,ubantu), Solaris (s8/s9/s10/nevada/open-solaris)
Posts: 303

Rep: Reputation: 32
returning address of stack variable in function


In function fun, address of stack variable(a) is copied to ptr.
But as soon as program control comes out of function, stack variables gets cleaned.
So inside main(), program should not have printed value of a.

But here, I am able to print the content inside main().
Is this expected ?

Code:
#include<stdio.h>
  
int* fun(int *ptr)
{
    int a=40;
    ptr=&a;
    return ptr;
}

int main()
{
    int i=20;
    int *ptr=&i;
    printf("\n %d",*fun(ptr));
    return 0;
}
Result:
Code:
./a.out
40
 
Old 01-23-2020, 09:11 PM   #2
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
humm
Code:
#include<stdio.h>
  
int* fun(int *ptr)
{
	printf("in fun ptr = %d before reassignment \n", *ptr);
    int a=40;
    // you are not assigning the prams ptr
    //your assigning 'a' to ptr over riding your pram ptr
    //so it is returning 40 like you programmed it to do.
    ptr=&a;
    printf("in fun a = %d ptr = %d\n",a, *ptr);
    
    return ptr;
}
int* fun2(int *ptr) { return ptr; }

int main()
{
    int i=20;
    int *ptr=&i;
    printf("main ptr = %d\n", *ptr);
    
    //your function is printing what is declared 
    // in your function 
    printf("in main\n %d\n\n",*fun(ptr));

    int *f, s;
    s = 32;
    f = &s;
    printf("fun2= %d\n", *fun2(f));
    return 0;
}
results
Code:
$ ./a.out
main ptr = 20
in fun ptr = 20 before reassignment 
in fun a = 40 ptr = 40
in main
 40

fun2= 32

Last edited by BW-userx; 01-23-2020 at 09:56 PM.
 
Old 01-23-2020, 09:40 PM   #3
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,866
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
@OP: What you see is accidental working, but what you should achieve is reliable working.
The memory on the stack might not have been overwritten that moment, but sooner or later it will be overwritten, and your data will be lost. Also stack is allowed to grow and shrink on demand, so a pointer that points to a currently unused stack-area might become invalid pointer that causes segmentation fault when you try to use the pointed value.

Last edited by NevemTeve; 01-23-2020 at 09:46 PM.
 
2 members found this post helpful.
Old 01-23-2020, 09:48 PM   #4
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,882
Blog Entries: 13

Rep: Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930
Quote:
Originally Posted by barunparichha View Post
In function fun, address of stack variable(a) is copied to ptr.
But as soon as program control comes out of function, stack variables gets cleaned.
So inside main(), program should not have printed value of a.

But here, I am able to print the content inside main().
Is this expected ?
Just because the stack gets popped, does not mean that the locations used by it are corrupt, in fact they typically are not until you make another function call. This does not mean that you're doing a correct thing. You shouldn't be returning a stack variable address to the calling function.

Your code is the reverse of how I'd pass a pointer and use it, crude example. I'd likely check for a NULL pointer and return a status from fun(), neither of which is done here:
Code:
#include <stdio.h>

void fun(int *ptr)
{
    *ptr = 20;
}

void main()
{
    int i=0;
    printf("Original value: %d\n", i);
    fun(&i);
    printf("New Value: %d\n", i);
}
 
Old 01-23-2020, 10:04 PM   #5
Geist
Member
 
Registered: Jul 2013
Distribution: Slackware 14 / current
Posts: 442

Rep: Reputation: 196Reputation: 196
This is playing the lottery.
Might work right now, might stop working if you use a different (version of the ) compiler, different optimizations, etc.

It's like using uninitialized variables.
Some hypothetical int in a different code might be initialized 'by itself' to 0x00000000 to you, might do it to 0xdeadbeef for someone else, or yourself at another compilation.
 
Old 01-23-2020, 10:16 PM   #6
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
more pointer math?
Code:
#include<stdio.h>
 
int* fun2(int *ptr) 
{
	 return ptr;
}
int* fun3(int *ptr) {
	int a = 10, g = 0;
	g = *ptr;
	*ptr=(a+g);
	return ptr; 
}

int main()
{
       
    int *f, s;
    s = 32;
    f = &s;
   
    printf("fun2= %d\n", *fun2(f));
    printf("fun3= %d\n", *fun3(f));
    return 0;
}
resutls
Code:
$ ./a.out
fun2= 32
fun3= 42

Last edited by BW-userx; 01-23-2020 at 10:24 PM.
 
Old 01-24-2020, 12:12 AM   #7
barunparichha
Member
 
Registered: Jun 2006
Location: Bangalore,india
Distribution: Linux(Redhat,fedora,suse,ubantu), Solaris (s8/s9/s10/nevada/open-solaris)
Posts: 303

Original Poster
Rep: Reputation: 32
Conclusion:
==============
1. such results are compiler specific.
2. so even after stack unwinding, variables take some time to cleanup.
 
Old 01-24-2020, 07:41 AM   #8
SoftSprocket
Member
 
Registered: Nov 2014
Posts: 399

Rep: Reputation: Disabled
Quote:
Originally Posted by barunparichha View Post
Conclusion:
==============
1. such results are compiler specific.
2. so even after stack unwinding, variables take some time to cleanup.
They don't really cleanup. When a function returns the portion of the stack that it has used is available for other uses. That means the results from continuing to access it in your program are undefined. Amongst the possible outcomes of using a pointer to a function local variable after the function has terminated is that you get the value assigned.

Memory assigned with malloc is allocated on the heap and until freed will remain available to your program so a pointer can be assigned to and returned from a function and safely used. A pointer to a local variable can be passed to a function and assigned then read after the function returns because it is on the calling functions stack, not the receiving function.
 
Old 01-24-2020, 08:07 AM   #9
dugan
LQ Guru
 
Registered: Nov 2003
Location: Canada
Distribution: distro hopper
Posts: 11,226

Rep: Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320
Huh. This prints out a warning:

Code:
#include <stdio.h>

int *fun()
{
    int a;
    a = 40;
    return &a;
}

int main()
{
    printf("%d\n", *fun());
    return 0;
}
Code:
stack2.c: In function ‘fun’:
stack2.c:7:12: warning: function returns address of local variable [-Wreturn-local-addr]
    7 |     return &a;
      |            ^~
But this does not:

Code:
#include <stdio.h>

int *fun()
{
    int a;
    int *b;
    b = &a;
    return b;
}

int main()
{
    printf("%d\n", *fun());
    return 0;
}
I guess the compiler just isn't smart enough to catch it when it's a pointer.

And clang-check didn't catch it either.

Last edited by dugan; 01-24-2020 at 08:12 AM.
 
Old 01-24-2020, 08:07 AM   #10
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,882
Blog Entries: 13

Rep: Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930
Quote:
Originally Posted by barunparichha View Post
Conclusion:
==============
1. such results are compiler specific.
2. so even after stack unwinding, variables take some time to cleanup.
Also in agreement with SoftSprocket's comment. You seem have misnomers about things like the stack, the heap, and how programs use them.

What would be helpful here is what you're trying to figure out or learn. Results are system specific and the stack is not cleaned up.

Why did you write that program initially, and what were you intending to explore/learn?
 
Old 01-24-2020, 08:20 AM   #11
dugan
LQ Guru
 
Registered: Nov 2003
Location: Canada
Distribution: distro hopper
Posts: 11,226

Rep: Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320
Let this be a lesson about the benefits of modern C/C++ tooling.

Code:
❯ cat stack3.c
#include <stdio.h>

int *fun()
{
    int a;
    int *b;
    b = &a;
    return b;
}

int main()
{
    printf("%d\n", *fun());
    return 0;
}
❯ cat Makefile
stack3.o:
	gcc -o stack3.o stack3.c
❯ bear make
gcc -o stack3.o stack3.c
❯ clang-tidy stack3.c
2 warnings generated.
stack3.c:8:5: warning: Address of stack memory associated with local variable 'a' returned to caller [clang-analyzer-core.StackAddrEscapeBase]
    return b;
    ^
stack3.c:13:21: note: Calling 'fun'
    printf("%d\n", *fun());
                    ^
stack3.c:8:5: note: Address of stack memory associated with local variable 'a' returned to caller
    return b;
    ^
stack3.c:13:5: warning: 2nd function call argument is an uninitialized value [clang-analyzer-core.CallAndMessage]
    printf("%d\n", *fun());
    ^
stack3.c:13:21: note: Calling 'fun'
    printf("%d\n", *fun());
                    ^
stack3.c:5:5: note: 'a' declared without an initial value
    int a;
    ^
stack3.c:13:21: note: Returning from 'fun'
    printf("%d\n", *fun());
                    ^
stack3.c:13:5: note: 2nd function call argument is an uninitialized value
    printf("%d\n", *fun());
    ^
I wrote a Makefile as an intermediate step towards generating the compilation database (compile_commands.json) needed to get clang's tooling to work, then I ran bear on that Makefile to generate said database. And then I ran the code through clang-tidy. That caught it.

Last edited by dugan; 01-24-2020 at 08:25 AM.
 
Old 01-30-2020, 06:27 AM   #12
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,515

Rep: Reputation: 239Reputation: 239Reputation: 239
i always find it more beneficial to concentrate on studying good code, not bad.
 
1 members found this post helpful.
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] read function call returning more amount of data than wiritten using write function chakka.lokesh Programming 1 09-11-2014 03:14 AM
bash catching the function returning value into a variable patolfo Linux - General 6 03-19-2010 11:58 AM
single 8K process stack vs 4K process stack and a seperate 4K interrupt stack charvak Linux - Kernel 1 03-17-2010 06:58 PM
Does user stack have a fixed address location in its virtual address? lqu Linux - Kernel 1 09-11-2009 01:28 PM
AWK a variable Ouptut to a new variable and using the new variable with the old one alertroshannow Linux - Newbie 4 02-16-2009 12:08 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:59 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration