While learning pointers I tried pointer declarations/dereferenciations.
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
int *call() {
int a = 3;
return &a;
}
int main() {
printf("call* is: %d\n", *call());
printf("call is: %p\n", call());
Sleep(2000);
printf("call* is: %d\n", *call());
printf("call is: %p\n", call());
Sleep(2000);
printf("call* is: %d\n", *call());
printf("call is: %p\n", call());
return 0;
}
So "obviously" the "a" is a local variable.
But my problem is,
when I'm reading out the address of "a", it's always the same address.
Why is that like this?
PS: I'm running a prime-number-calculator in the background to fill up as much memory as possible and I put in the "Sleep" to make the program wait, but still the address of "a" is always the same.
a is located on the stack of the current thread : every time the function call() is run, it "allocates" 4 bytes on the stack to stock a, return the address and then "frees" the space it uses on stack (it is not actually allocating/freeing anything, just offsetting the stack pointer).
So if you call it several times in a row, the state of the stack on input of the function will be exactly the same, so the actual address of a on the stack the same every time (please note that this address is invalid as soon as you exit the function).
You should do something like
int * call2(){
int a = 0;
int *b = call();
printf("%d",a);
return b;
}
and then
int *a = call();
int *b = call2();
You will see a and b will be different (the printf is there to make sure the compiler does not optimise anything away)
Since the stack is local to the current thread (not influenced by other processes/threads), your prime number calculator and Sleep are to no use at all.
"call" is to return a pointer to a variable? The problem here is that "a" is not statically allocated, but is on the stack. You can return its address at the moment (which may or may not be the same address, depending on whether "call" is invoked at the same depth each time), but there's no guarantee of what that address is pointing to once you return from "call". You put a 3 in it during the call, and that may be overwritten by something else by the time you get around to looking at the contents of that address.
Related
I have the following C program:
#include <stdio.h>
void setArr(int, int);
int *arr[10]; // array of 10 int pointers
int main(int argc, char *argv[])
{
int i;
setArr(0, -10);
setArr(1, 100);
setArr(2, 200);
setArr(3, 300);
setArr(4, 400);
for (i = 0; i < 5; i++)
printf("arr[%d] -*-> %d %d\n", i, *arr[i], **(arr + i)); /* should be -10,100, 200,300,400 */
return 0;
}
/* set arr[index], which is a pointer, to point to an integer of value v */
void setArr(int index, int v)
{
int i = v;
arr[index] = &i;
}
It gives the following output:
arr[0] -*-> 400 400
arr[1] -*-> 400 400
arr[2] -*-> 400 400
arr[3] -*-> 400 400
arr[4] -*-> 400 400
What I understand is that each element in the arr is a pointer and it will point to the location of the variable i created inside the function.
I am not sure how it could be consistently returning 400 always
What could be the reason for this output and how to correct it?
The definition int i = v; inside a function automatically reserves memory for i. When execution of the function ends, the memory reservation is released.
Once the memory reservation is released, the C standard does not guarantee the value of any pointers to the memory, and you should not use those values.
Each time you call setArr, the memory is reserved and then released. A common result is that the same memory is used as it is reserved, released, reserved, released, and so on, and that the pointer appears to point to the same location. Then you have set every element of arr to point to the same location. However, optimization and other actions by the compiler can produce other behaviors.
Of course, that location can hold only one value at a time, so only one value is seen in it at after the calls to setArr.
Your code makes no sense.
For starters, in C, the address of a local variable like i will not be valid once the function containing it exits.
This means all pointers in your array are not valid outside setArr.
Second, C compilers usually allocate local variables on the stack, which means i would likely be at the same address for every call to setArr, so the output you are seeing is perfectly logical.
The value of i gets overwritten every call, and because you print it immediately after last call to setArr the memory, though technically free, has not been overwritten yet.
So, by luck, you get to see the result of last call to setArr in all your printf calls.
I was trying to understand the concept of passing by reference. When I do this,
#include<stdio.h>
int recent (int *a)
{
*a = 20;
return 0;
}
int main()
{
int bee;
bee=5;
int *val = &bee;
printf("Value is %d\n", *val);
recent(val);
printf("Now Value is %d\n", *val);
return 0;
}
Basically I am making the pointer val point to the memory location of bee, and then when I pass it to recent function, and change the value, that change gets reflected in the calling function, so the value changes to 20. But when I do this,
#include<stdio.h>
int check = 20;
int recent (int *a)
{
a = ✓
return 0;
}
int main()
{
int bee;
bee=5;
int *val = NULL;
recent(val);
printf("Now Value is %d\n", *val);
return 0;
}
I get segmentation fault.
Is it because I didn't initialize the pointer to point to any location, and then I passed the value to recent function, and even though I made it point to a memory location (check variable), the calling function didnt catch that because I was passing by value?
Is this completely true or I misinterpreted something and got lucky with the answer?
Your problem is that you are printing the output of dereferencing the pointer val in the main function. The value of the pointer val in the main function is NULL. Thus the program is trying to print the thing at memory location 0, which is inaccessible to your program and results in a segmentation fault.
First you create the val pointer and assign it the value NULL.
int *val = NULL;
Then you call recent, passing it the pointer val, which still holds NULL.
recent(val);
Finally you print *val. val still holds NULL, and the * operator tells the compiler to "dereference" val, meaning to use the value of the thing that val is pointing to.
printf("Now Value is %d\n", *val);
In response to the question of whether your description is correct, the answer is sort of, but your description is imprecise. You made the function's copy of the pointer point to something. When you implement a pass-by-reference function in C using pointers, you are still passing the pointers themselves by value: a copy of the pointer is made, pushed onto the stack, and sent to the function. If you update the value of the pointer in the called function, the value of the pointer in the calling function will not be changed.
The reason has to do with your function recent(). When you pass in "a" you are passing in an int* (i.e. int pointer) which is an address to a location in memory. However, "a" as you have it, is local to this function (the pointer is pass by value).
Thus when you set "a = &check", you are only changing the local pointer value. As soon as recent() returns, "a" goes out of scope. In this context, you are never changing what "a" actually points to.
Thus, you segfault because val is still null, and you are trying to dereference a NULL pointer.
val is still a null pointer after leaving the function. The pointer itself is (as you correctly guessed) only passed by value, not by reference. Inside the function you are only modifying the pointer (which only lives insides the function), not the pointer target.
Besides that, please be careful with passing around memory locations to automatic stack variables. At least coming from a C++ background, it's considered bad style. Since you don't explicitly control the life cycle of a stack variable yourself (as you would do with malloc/free), you can easily shoot yourself in the foot by accidentally dereferencing pointers which have already been cleaned from the stack.
Is it because I didn't initialize the pointer to point to any location,
Code well initialized with int *val = NULL;, yet NULL is not a valid location. It isn't the NULL is a location or not. It is the NULL is the null pointer constant. As a null pointer, it "is guaranteed to compare unequal to a pointer to any object or function."
... and even though I made it point to a memory location (check variable), the calling function didn't catch that because I was passing by value?
Yes. With a = ✓, only the local a was affected, not the val in which a was copied from as the actual augment val was passed by value (copied) to the formal parameter a.
Is this completely true ...
IMO: Yes
... I misinterpreted something and got lucky with the answer?
It appears no misinterpretation. Lucky - hard to rate.
Here is what is going on in your code:
#include<stdio.h>
int check = 20;
int recent (int *a)
{
a = ✓
return 0;
}
int main()
{
// memory is allocated to hold an integer
int bee;
// the number 5 is written into that memory space
bee = 5;
// memory is allocated to hold a memory address
// the value of null (which is a invalid address) is written into it
int *val = NULL;
// more memory is allocated to hold a memory address (int* a)
// the address in val (which is null) is written into it
// the new memory address (a) now points to the address of check
recent(val);
// val is still NULL
// BOOOM!
printf("Now Value is %d\n", *val);
return 0;
}
Long story short, you are correct! :)
It's basically what all have answered. It's because you are passing the address pointed by pointer a using Pass By Value method. That is your sending in a copy of the address. If you want the second code to work you need to change the code to the following,
#include<stdio.h>
int check = 20;
int recent(int **a)
{
*a = ✓
return 0;
}
int main()
{
int bee;
bee = 5;
int *val = NULL;
recent(&val);
printf("Now Value is %d\n", *val);
return 0;
}
That is you have to Pass the address pointed by a by using C version of "Pass By Reference".
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 8 years ago.
This is a question from a C language course. Someone wants to return a value from a function with a pointer. He assigns the pointer address to result_ptr and prints this pointer's value.
When there is no Line A, printf() works fine: printf() prints 3.
However, when another addition() function is called in front of the printf(), something wrong happens: the printf() prints 5.
If Line A is commented out and Line B, another printf() function, is uncommented: the printf() prints 0.
What exactly is going on?
int *addition(int a, int b) {
int d = a + b;
int *c = &d;
return c;
}
int main(int argc, const char * argv[])
{
int *result_ptr = addition(1, 2);
addition(2, 3); // Line A
// printf("Another line\n"); // Line B
printf("result = %d \n", *result_ptr);
return 0;
}
When a function is called, the arguments (in reversed order), the return address and the Caller's EBP (which stores where the function returns to after execution) are pushed onto the stack. The callee setups a stack frame that stores its local variables and saves contents of 3 registers, EBX, ESI and EDI if they are modified. When the function finishes execution, the frame is popped and the stack's top returns to the height where it had been before the callee was called.
In this example, int *c declares a local pointer variable that is stored on the stack within the callee's frame. Returning that pointer is returning an address on the stack frame. As consecutive addition() calls cause identical stack space allocations, content of the same address will be written twice. This is why the second function call will write 5, overwriting 3 from the first function call: they are modifying the value at the same memory location. When printf() is called, however, the stack space is used for a totally different stack frame. Then the same location stores an undefined value.
To avoid this, it would be better to return a pointer to a location on the heap instead of on the stack. Mind to free the pointer after memory allocation to avoid leakage.
int *addition(int a, int b) {
int *c = (int *) malloc(sizeof(int));
*c = a + b;
return c;
}
// in main
int *result_ptr=addition(1,2);
printf("value = %d \n",result_ptr);
free(result_ptr);
result_ptr=0;
Reference: http://www.csee.umbc.edu/~chang/cs313.s02/stack.shtml
I will be glad to see clearer or different explanations for this question.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Say I have something like:
function2(int *hello) {
//something
}
function1(int *hello) {
function2(&hello);
}
void main() {
int hello = 0;
function1(&hello);
}
How do I make it so that function2 can change the original value declared in main?
Change this code:
function1(int *hello) {
function2(&hello);
}
to:
function1(int *hello) {
function2(hello); // <-- no "&" in this call!
}
Then you can do this:
function2(int *hello) {
*hello = 123; // <-- dereference pointer hello
}
You are making a mistake in the function1 where your pass the address of the pointer to your int hello in the main function. you pass the pointer forwart to the function2 and the dereference it in there.
function2(int *hello) {
*hello = 123 ;
}
function1(int *hello) {
function2(hello); //pass the pointer on to function2
}
int main( void ) {
int hello = 0;
function1(&hello);
return 0 ;
}
You are also incorrectly declaring your main function. It should be declared as int main() with a return statement.
As mvp reply it is correct answer but i am here just explaining something, which will help you to understand, why your code is not working.
First let me explain operator you used
1] Ampersand Operator (&)
This operator helps you to get reference/address of variable
As soon as we declare a variable, the amount of memory needed is assigned for it at a specific location in memory, As we generally do not actively decide the exact location of the variable within the operating system during run time but some time we need to know address of our variable like here You want to know the address of variable to assign it's address to pointer The address that locates a variable withing memory is what we call a reference to that variable Which we can get using Reference variable.
Dereference Operator (*)
As we know that pointer is the variable which will store that address of the another variale, using pointer we can directly access the value stored in the variable which it points.To do this we simply have to precede the pointer's identifier with an asterisk (*), which acts as deference operator and that can be literally translated to value pointed by
Now back to your code
function2(int *hello) { // Here you create function that accept address of variable (You will get address of hello pointer 101 NOT 100 of variable assign in your MAIN)
//something
}
function1(int *hello) {// Here you create function that accept address of variable (Here it will get address of hello which is 100)
function2(&hello); // Here you again pass address of your pointer hello (Which may be 101) [BAD]
}
main {
int hello = 0; // Let say it's address is 100
function1(&hello); // Here you pass address of your variable(which is 100) [GOOD]
}
Solution is as suggested
function2(int *hello) {
//Change your value here
*hello = 123;
}
function1(int *hello) {
function2(hello); // It will pass 100 (address of your variable hello assign in MAIN
}
main {
int hello = 0;
function1(&hello);
}
The "&" operator means "address of", so your function 1 is trying to call function2 with the address of "hello" rather than the address hello contains.
Responding to a different question I said this:
Pointers are variables which store a number, like any other, but because you tell the compiler it is a pointer, the compiler allows you to use that value as an address of things in memory and the language provides "dereferencing" as a way of saying "the value AT the address this variable describes".
Imagine you're going to the airport to catch a flight. You grab a post-it note and write down your flight number, and you take a second post-it with you for your gate.
The first post it is a "flight*" pointer and your second is a "gate*" but right now the gate* pointer is empty.
When you get to the airport, you look up your flight on the board and jot down the gate number. "3A". Now your gate* post-it is valid.
But the post-it itself is NOT your gate, it just points to it: you still have to "dereference" the post-it note to get to your flight - that is, walk across the airport to gate 3A :)
When you called function1 you took the address of the variable in main. All you need to do is forward it to function2. What your code was trying to do was make a note of which post-it not the gate number was on, rather than just looking at the post-it note.
Solution
#include <stdio.h>
void function1(int*); // so the compiler knows what the function looks like.
void function2(int*);
int main() {
int varInMain = 0; // lets call it something distinct
printf("varInMain starts with %d, it's location in memory is %p.\n",
varInMain, &varInMain);
function1(&varInMain);
printf("varInMain is %d after calling function1.\n", varInMain);
return 0;
}
void function1(int* func1ptr) {
printf("function1: func1ptr points to memory location %p, which contains %d.\n",
func1ptr, *func1ptr);
*func1ptr = 1010;
function2(func1ptr);
}
void function2(int* func2ptr) {
printf("function2: func2ptr points to memory location %p, which contains %d.\n",
func2ptr, *func2ptr);
*func2ptr = 123;
}
You can see a live demo of this code on ideone.com here.
Output looks like this:
varInMain starts with 0, it's location in memory is 0xbfef2fdc.
function1: func1ptr points to memory location 0xbfef2fdc, which contains 0.
function2: func2ptr points to memory location 0xbfef2fdc, which contains 1010.
varInMain is 123 after calling function1.
I am writing the following code that will be able to change the stack of function call. but it always runs into segfault on printf. I debugged the code with assembly, the stack was successfully switched. it is the printf statement that created the segfault and not sure the reason. anybody has any clue what direction i should look into more?
Thanks.
char stack[4000000*4];
void foo(int ad) {
int i = 100;
int sum = i*i + ad;
printf("stack changed to %X\n", stack);
}
/* in this example, foo (and its decendents) live on a new stack */
void change_stack(void *newstack) {
void *ctx[5]; // Jump buffer for setjmp/longjmp.
if (0 == __builtin_longjmp(ctx)) {
ctx[2] = newstack; // switch stack
__builtin_longjmp(ctx, 1);/* here stack is switched */
} else {
/* now live on new stack, can we pass parameters now ? */
int ad = 20;
foo(ad);
}
}
int main (int argc, char** argv)
{
int i = 10;
change_stack(stack);
printf("return, %d\n", i);
return 0;
}
You switch stacks without copying the contents of the old one. When change_stack returns, the results are undefined (it may, for example, jump to address NULL, causing a segfault). Also, things like local variables will also be undefined.
Also, (assuming we're talking x86 here), the stack pointer is decremented on pushes. Since the new stack pointer you assigned is the base (i.e. lowest) address of your stack array, any push will decrease the pointer outside of this array, also possibly resulting in a segfault.
To anyone who still wants to play with the stack and also encountered SIGSEGV in printf, here is an important point:
You can find one of the subroutines of printf, __GI___tcgetattr under /path-to-glibc/sysdeps/unix/sysv/linux/tcgetattr.c. There is one instrution in it:
movdqa (%rsp),%xmm0
And according to this answer, it reads 16-byte align memory from source address. So you should keep the address of %rsp at least 16-byte address align when you switch the stack, otherwise you will get a SIGSEGV.