why does this function return garbage value - c

I was writing a program and facing this problem that the following function used to return garbage values:
int* foo(int temp){
int x = temp;
return &x;
}
When I modified it to this, it worked fine:
int* foo(int *temp){
int *x = temp;
return x
}
What was wrong with the first version?

The first version returns a reference to a local variable x whose storage is limited to the function foo. When the function exits, x can no longer be used. Returning a reference to it is one instance of a dangling pointer.
In the second version, you're really only passing in and returning the same pointer value, which refers to memory which isn't limited by the lifetime of the function. So even after the function exits, the returned address is still valid.
Another alternative:
int *foo(int temp)
{
int *x = malloc(sizeof(int));
*x = temp;
return x;
}

For each function there will be an activation record, which will be created in stack once the execution of that function starts. Activation record holds all the local variables also. And this activation record will be freed once the function execution finishes.
So if we return an address of a local variable means, that will be freed memory of previous function`s activation record. Dereferencing that memrory is an undefined behaviour.
In the below case, function foo is returning the &x that means p will holds the address of func's local variable x. This is valid. But if function func tries to retrun p(address of x) which is not valid.
int* func
{
int x;
int *p;
...
p = foo(&x);
//using p is valid here
...
return p; //This is invalid
}
int* foo(int *temp)
{
int *x = temp;
return x //This is valid
}
In the below case, funciton foo is returning address of its local variable x to function func. So p will holds address of foo's local variable. So deferencing p is invalid because foo functions execution has been completed and its activation record is freed.
int* func
{
int x;
int *p;
...
p = foo(x);
//using p is invalid here
...
return p; //This is invalid
}
int* foo(int temp)
{
int x = temp;
return &x; //This is also invalid
}

Related

Can i return address of a variable in a function of return type pointer? [duplicate]

This question already has answers here:
How to access a local variable from a different function using pointers?
(10 answers)
Return a pointer that points to a local variable [duplicate]
(3 answers)
Closed 3 years ago.
I am trying to understand how pointer to a variable and address of a variable works.
When I am writing the following code :
#include<stdio.h>
int* g(void){
int x = 10;
int *p = &x;
printf("%p,%p",p,&x);
return (p);
}
void main(){
int * p = g();
printf("\n%d",*p);
}
Output:
0060FED8,0060FED8
10
Process returned 3 (0x3) execution time : 0.031 s
Both the address and pointer to x gives the same value, but when i am returning address &x instead of pointer p the code doesn't print the value of x anymore:
#include<stdio.h>
int* g(void){
int x = 10;
int *p = &x;
printf("%p,%p",p,&x);
return (&x);
}
void main(){
int * p = g();
printf("\n%d",*p);
}
Warning:
warning: function returns address of local variable [-Wreturn-local-addr]
Output:
0060FED8,0060FED8
Process returned -1073741819 (0xC0000005) execution time : 8.332 s
Can anyone tell me what am I doing wrong?
What you have been observing is an Undefined Behaviour. There is something called Storage Class in C programming language. The variables inside your function int *g(void) has automatic storage class. They have a lifetime and scope of your function. Whenever you get out of your function, the location allocated for your variables (x and *p) will be destroyed.
So, it doesn't make sense to use address of variables with automatic storage class outside their scope, i.e., outside your function (int *g(void)) as the pointer returned will be a dangling pointer.
You can make use of heap dynamic memory to allocate the space if you want to learn or use memory location outside the function scope.
You can also make use of global variable and return memory address of that global variable from your function.
#include <stdio.h>
#include <stdlib.h>
int x = 10;
int *g(void)
{
int *p = &x;
printf("%p,%p\r\n", p, &x);
return (&x);
}
int *heap(void)
{
int *p = malloc(sizeof(int));
*p = 100;
printf("%p\r\n", p);
return p;
}
int main(void)
{
int *p = g();
printf("%d\r\n", *p);
int *p1 = heap();
printf("%d\r\n", *p1);
return 0;
}
Since x isn't allocated memory on the heap with malloc or calloc, it's instead allocated on what's called the stack. The stack is used for primarily local variables. A local variable exists only within the scope it's declared. A scope is in poor man's terms, anything between two sets of matching braces.
int* g(void){
//x is allocated on the stack, since malloc wasn't used
int x = 10;
//p is pointing to x's spot in memory (on the stack)
int *p = &x;
//These addresses are the same, all is well so far
printf("%p,%p",p,&x);
//We return the memory location of x
//However, since this is the end of this scope (this function), any variables on the
//stack from this scope will be deleted, which means by the time we get back to main
//the variable "x" was deleted, so its spot in memory doesn't mean anything
return (&x);
}
Function g has x declared as local variable. This means that x is only seen/available to function where it is declared. Passing pointer of x to main is useless since x is not visible to main() function. It is always bad practice to return using pointer unless necessary.

scope of the variable in c using pointers and functions

#include<stdio.h>
int i = 10;
void func(int *q){
q = &i;
}
int main(void){
int i = 20;
int *p = &i;
printf("%d\n",*p);
func(p);
printf("%d",*p);
return 0;
}
here value of p in 2nd printf statement should be 10... but when I execute it returns 20 how n why?
It would print 10 if you do this
*q = i
in the called function.
Change the content of that variable whose address is with you in the called function in the local variable q. Don't change the content of the local variable q.
You asked me why? Will explain...
This is what happened when you called the function and printed the value. Well this is not an exhaustive list but this points out the key things that will help in this context.
You got the address of the variable i in p.
Then you pass it to the called function.
Called function now has a local variable whose content is same as that of p.
Now you change the content of that local variable with the address of the global variable i.
Then function ends.
Rest in peace - local variable q. It is dead.
Then you again access *p in main() - meaning you looking for what value there is in the address contained in p.
you get 20.
Is there any other way to get 10?
Well there is
func(&p);
And then you do this
void func(int **q){
*q = &i;
}
Now you print *p you will get 10.
Know few things clearly, no matter what C is pass by value. Even here also q is a local variable. But now we have the address of p of main()
in q. So when you write *q=&i then you are basically going to the address of p from main() and then write there the address of global variable i. Then you come back. q is again lost. Then you print it - as you change to the original variable (p), the content there is 10.
Code-1
func(p);
then in func()
void func(int *q){
*q = i;
}
Code-2
func(&p);
then in func()
void func(int **q){
*q = &i;
}
Here
q = &i
You are setting the value of q, which is a local variable. Changing it does not change the value of the variable passed to func().
To have the 2nd call to printf() print 10, you want to write to where q is pointing.
*q = i;
q points to the inner i, which this way is set to 10.
here value of p in 2nd printf statement should be 10 (changed) ... but when I execute it returns 20 (same as original).
How and why?
q in void func(int *q) is a copy of p when func(p); is called.
void func(int *q){
q = &i;
}
int main(void){
...
func(p);
...
}
The change q = &i; inside void func(int *q) does not affect p in main().

Functions can return values but not Address without pointer variable

Why we can return the value of a local variable from a function but not it's address? Such as we can write 'return a' but not 'return &a' in C.
A modified version of your example in the comments:
#include <stdio.h>
int* f() {
int a = 6, *p;
p = &a;
return p;
}
int g() {
int a = 6;
return a;
}
int main() {
int x = g();
int* y = f();
}
Both f and g return by value.
One returns an int and stores the value in x. Now x holds the value 6 previously in a.
The other function returns a pointer and stores the pointer value in y. Now y holds the value previously stored in p.
The problem is just that the pointer is now invalid (dangling), as the thing p pointed to no longer exists.
Actually, you can.
But you have to define your function correctly like this:
int a = 0;
int* ReturnValAddress()
{
return &a;
}
Although you can send any local variable address, pay attention please that sending the function's local variable address does not have any meaning because right after returning, local variables would die!!, but you can send global variable address like above code.

what will be the output of the following snippet?

what's happening after clrscr?
#include<stdio.h>
#include<conio.h>
int *call();
void main()
{
int *ptr;
ptr=call();
clrscr();
printf("%d",*ptr);
getch();
}
int*call()
{
int a=25;
a++;
return &a;
}
output:
-10
code works like this:
call() is called, a=25, then a=26. let address of a be 65518. this address is returned to ptr. since return type is int, instead of 65518, (due to cyclic property) -18 is returned.
so ptr=&a=-18. then clrscr clears it....but how *ptr is printed as output? i mean address cannot be negative(-18).
Returning a pointer to local is undefined behavior. Anything could happen - your program could crash, but more likely it is going to print some arbitrary number.
If you need to return a pointer from a C function, you need to either allocate a memory block in the dynamic storage, like this:
int*call()
{
int *a=malloc(sizeof(int));
*a = 25;
*a++;
return a;
}
or use a pointer to a statically allocated block, like this:
int* call()
{
static int a=25;
a++;
return &a;
}
If you choose the dynamic allocation route, the caller must free the pointer returned by your function.
int*call()
{
int a=25; // <--- use malloc here i.e. int a = malloc(sizeof(int)); then you can set a value to a and return the pointer without any problemk, OTHERWISE => it will return an address of some random junks you don't want, its gonna be completely random
a++;
return &a;
}
When call() is called, a new stack frame is created with space for the local variable a, which has its lifetime during the execution of call(). When it returns, the stack frame is removed along with its local variable(s) and data. Trying to use this data outside the function is undefined, because it no longer exists, logically.
If you want to declare a inside a function and use it afterwards, you'll need to allocate it:
...
int *a = malloc(sizeof int);
*a = 26;
return a;
...
Remember to free() this pointer after you're finished using it.

passing a pointer as argument to a function in C

Something I stumbled upon and made me wonder.
Why does this work?
void foo (int* a)
{
int x = 3;
*a = x;
}
int main()
{
int a;
foo(&a);
return 0;
}
But this causes a segmentation fault (both on Visual Studio 2008 and gcc)?
void foo (int* a)
{
int x = 3;
*a = x;
}
int main()
{
int* a;
foo(a);
return 0;
}
Is it something defined in the language or just an implementation issue?
When you declare
int* a;
You are declaring a pointer variable a but you are not making it point to anything. Then in the function, you do
*a = x;
Which dereferences the pointer and tries to assign what it points to the value of x. But since it doesn't point to anything, you get undefined behaviour, manifested in a segmentation fault.
You should do this:
int i; // the actual integer variable
int* a = &i; // a points to i
The difference between that and the first one is that int a; declares a real integer variable, then you take its address with &a and passes it to the function. The pointer a inside the function foo points to the variable a in main, and so dereferencing it and assigning to it is perfectly fine.
int a;
Assigns memory as soon as you declare it but this not the case with int *a;
int *a;
is pointer declaration (MEMORY not yet allocated for that).
int *a = (int*)malloc(sizeof(int)); // allocate memory

Resources