this is the code :
#include <stdio.h>
#include <stdlib.h>
int main() {
int a = 10;
int b = 20;
//printf("\n&a value %p", &a);
int* x = &b;
x = x + 1;
*x = 5;
printf("\nb value %d", b);
printf("\na value %d", a);
}
I want override a with b adress for test the c overflow but when I comment the line 5(printf fuction) I can't write five in a. While if I print the a adress I can write five in a.
Why?
Sorry for my english and thank you.
The reason this occurred is that all normal compilers store objects with automatic storage duration (objects declared inside a block that are not static or extern) on a stack. Your compiler “pushed” a onto the stack, which means it wrote a to the memory location where the stack pointer was pointing and then decremented the pointer. (Decrementing the pointer adds to the stack, because the stack grows in the direction of decreasing memory addresses. Stacks can be oriented in the other direction, but the behavior you observed strongly suggests your system uses the common direction of growing downward.) Then your compiler pushed b onto the stack. So b ended up at a memory address just below a.
When you took the address of b and added one, that produced the memory address where a is. When you used that address to assign 5, that value was written to where a is.
None of this behavior is defined by the C standard. It is a consequence of the particular compiler you used and the switches you compiled with.
You probably compiled with little or no optimization. With optimization turned on, many compilers would simplify the code by removing unnecessary steps (essentially replacing them with shortcuts), so that 20 and 10 are not actually stored on the stack. A possible result with optimization is that “20” and “10” are printed, and your assignment to *x has no effect. However, the C standard does not say what the behavior must be when you use *x in this way, so the results are determined only by the particular compiler you are using, along with the input switches you give it.
After x = x + 1;, x contains an address that you do not own. And by doing *x = 5; you are trying to write to some location that might not be accessible to you. Thus causing UB. Nothing more can be reasoned about.
Related
I am not clear for how long a variable is guaranteed to be allocated in C.
For example, if I have:
void foo(void) {
int x;
int* y = &x;
...
}
Is the space allocated on the stack for x guaranteed to be reserved for this variable exclusively for the entire duration of foo()? Said differently, is y guaranteed to point to a location that will be preserved for the entire duration of foo, or could the compiler decide that since x isn't being used, the stack space can be used for another use within foo and therefore *y may change without accessing y (or x) directly?
When you ask questions like this, you should be clear whether you are asking about C semantics or about program implementation.
C semantics are described using a model of an abstract computer in which all operations are performed as the C standard describes them. When a compiler compiles a program, it can change how the program is implemented as long as it gets the same results. (The results that must be correct are the observable behavior of the program: its output, including data written to files, its input/output interactions, and its accesses to volatile objects.)
In the abstract computer, memory for x is reserved from the time an execution of foo starts until that execution of foo ends.1, 2
So, in the abstract computer, it does not matter if x is used or not; memory is reserved for it until foo returns or its execution is ended in some other way (such as a longjmp or program termination).
When the compiler implements this program, it is allowed optimize away x completely (if it and its address are not used in any way that requires the memory to be reserved) or to use the same memory for x that it uses for other things, as long as the uses do not conflict in ways that change the observable behavior. For example, if we have this code:
int x;
int *y = &x;
x = 3;
printf("%d\n", x);
int b = 4;
printf("%d\n", b);
then the compiler may use the same memory for b that it uses for x.
On the other hand, if we have this code:
int x;
int *y = x;
printf("%p\n", (void *) y);
int b = 4;
printf("%p\n", (void *) &b);
then the program must print different values for the two printf statements. This is because different objects that both exist at the same moment in the abstract computer model must have different addresses. The abstract computer would print different addresses for these, so the compiler must generate a program that is faithful to that model.
Footnotes
1 There can be multiple executions of a function live at one time, due to nested function calls.
2 Sometimes people say the lifetime of x is the scope of the function, but this is incorrect. The function could call another routine and pass it y, which has the address of x. Then the other routine can access x using this address. The memory is still reserved for x even though it is not in the scope of the other routine’s source code. During the subroutine call, the execution of foo is temporarily suspended, but it is not ended, so the lifetime of x has not ended.
The lifetime of an automatic variable is the entire duration of the scope in which it is declared; in your case, that scope is the whole of the foo function.
Compilers are allowed to make optimizations (including removing variables completely) that can have no possible observable effect; however, once you assign the address of x to y, then any use of *y will be using x, so the memory allocated for x cannot then be used for something else, all the time there is a possibility of accessing or modifying *y.
x is being used, y is being passed the address of it! In short the answer is "yes" as long as the compiler author(s) is(are) sensible. Most compilers ( visual studio at least ) wouldn't compile this or at least warn that x is uninitialized so this isn't a very realistic example.
Y most definitely cannot change by changing another variable than x or y. that's 100%. When you go into a function the parameters then the local variables are pushed onto the stack and then when you come out of a function they are popped off. There is no scope for shared memory (unless you are using a union).
Whats the reason behind this question? If you really want to know how c is defined you should read "The C Programming Language" by Kernighan and Ritchie"
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a=10 ;
int *p;
p = &a;
*(p+1) = 20;
printf("The value at (p+1) is %d\n",*(p+1));
return 0;
}
I'm trying to do some pointer arithmetic and trying to implement the code. I'm trying to assign value 20 to next address in the memory using *(p+1) and print it using the printf statement, but my code isn't producing any output. Why is it so?
In the following:
int a=10 ;
When a is declared and initialized, 10 is placed in memory at the location it was created, as indicated in the following depiction of memory:
|?|10|?|...
^
a
Then the statements
int *p;
p = &a;
create a pointer p, the set the pointer to point to the same location
|?|10|?|...
^
p
In the statement *(p+1) = 20;
*(p + 1) references a place in memory that your process does not own, 1 memory location beyond a
|?|10|?|...
^
attempting to assign a value there invokes undefined behavior.
This actually hits me in a very dubious manner. I get Segmentation fault in the code. We had different results.
Firstly, who gave you any guarantee that p + 1 is even memory? It could very well be 0x00. No joke! You could be on a weird system in which the memory works backwards and if &a is 0x04, then a + 1 would be 0x00. There is no system in which memory is backwards for some reason, but it could happen. I don't think the standard enforces anything related to this(correct me if I'm wrong). This would just create confusion, no wonder nobody has tried this.
Secondly, who gave you any guarantee that p + 1 is not already used? The compiler might be using it, which it does very often.
Thirdly, who gave you any guarantee that picking up some memory that you haven't allocated will even work? Allocating memory is basically reserving memory, if you don't do that nothing is guaranteed to work. Imagine a bus. If you won't reserve a seat, there's no guarantee that you'll be able to sit on it.
So what happens? Undefined behaviour! Basically, if this situation is reached, then the compiler could make code that sends death threats to the president and enrols you for Militia training from a terrorist organisation and the compiler could still call itself "ISO/IEC 9899:2018 compliant". Unless there's an all-catching "compiler can't insert malicious code" phrase in the standard. I haven't checked. Yeah, this is why you should not use obscure compilers. Jokes aside, basically anything could happen, god and only god knows what will happen. Not even the compiler, not you, not ISO know what is going to happen. And that's why "undefined behaviour"s are so dreaded. Don't do weird stuff with memory.
Btw, the thing that makes this especially funny is that &p, with most compilers would be the same as p + 1 on 32 bit systems. And it probably overlap in 64 bit systems. Note the word probably, there's no guarantee.
Look at it this way, *(p + 1) is the same as having p[1] this means you are looking for a[1] but a is not an array, a[1] does not exist in your program, you can't either read or write in that memory location, we don't really know what's in there, that is why your program suffers from undefined behavior.
'a' is an normal integer you cant navigate trough the elements because there are no elements.
it is just an normal pointer to a variable.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a[10];
*(a+1) = 20;
printf("The value at (p+1) is %d\n",*(a+1));
return 0;
}
i thinkt this is what you want
#include<stdio.h>
int main()
{
int a,b;
float e;
char f;
printf("int &a = %u\n",&a);
printf("int &b = %u\n",&b);
printf("float &e = %u\n",&e);
printf("char &f = %u\n",&f);
}
The Output is
int &a = 2293324
int &b = 2293320
float &e = 2293316
char &f = 2293315
But when i use this code and replace the printf for float--
#include<stdio.h>
int main()
{
int a,b;
float e;
char f;
printf("int &a = %u\n",&a);
printf("int &b = %u\n",&b);
printf("char &f = %u\n",&f);
}
Then the Output is
int &a = 2293324
int &b = 2293320
char &f = 2293319
here address is not provided to float, but it is declared on top.
My questions are
Is memory not allocated to variables not used in program?
Why addresses allocated in decreasing order. ex- it's going from 2293324 to 2293320?
1) Is memory not allocated to variables not used in program?
Yes that can happen, the compiler is allowed to optimize it out.
2) Why addresses allocated in decreasing order. ex- it's going from 2293324 to 2293320?
That is usual for most local storage implementations, that they use the CPU supported stack pointer going from stack top to stack bottom. All those local variables will be allocated at the stack most probably.
1) Is memory not allocated to variables not used in program?
It's an allowed optimization; if an unused variable doesn't affect the program's observable behavior, a compiler may just discard it completely. Note that most modern compilers will warn you about unused variables (so you can either remove them from the code or do something with them).
2) Why addresses allocated in decreasing order. ex- it's going from 2293324 to 2293320?
The compiler is not required to allocate storage for separate objects in any particular order, so don't assume that your variables will be allocated in the order they were declared. Also, remember that on x86 and some other systems, the stack grows "downwards" towards decreasing addresses. Remember the top of any stack is simply the location where something was most recently pushed - it has nothing to do with relative address values.
While not specifically required by the standard, local variables are universally located on the program stack.
When you enter a function, one of the first thing done is to decrement the stack pointer to provide space for the local variables.
SUBL #SOMETHING, SP
Where SOMETHING is the amount of space required and SP is the stack pointer register.. In your first example, SOMETHING is probably 13. Then the address of:
f is 0(SP)
e is 1(sp)
b is 5(sp)
a is 9(sp)
I am assuming your compiler did not align the stack pointer. Often they do giving something more like:
f is 3(SP)
e is 4(sp)
b is 8(sp)
a is 12(sp)
And SOMETHING would be rounded up to 16 on a 32-bit system.
You might want to generate an assembly listing using your compiler to see what is going on underneath.
Is memory not allocated to variables not used in program?
Note that for local variable memory is not really allocated. A variable is temporarily bound to a location on the program stack (stack is not required by the standard but is how it is done in most cases). That is why the variable's initial value is undefined. It could have been bound to something else previously.
The compiler does not need to reserve space for variables that are not used. They can be optimized away. Usually, there are compiler settings to instruct not to do this for debugging.
Why addresses allocated in decreasing order. ex- it's going from 2293324 to 2293320?
Program stacks generally grow downward. Starting ye olde days, the program would be at the bottom of the address space, the heap above that and the stack at the opposite end.
The heap would grow towards higher addresses. The stack would grow towards the heap (lower addresses).
While the address spaces can be more complicated than that these days, the downward growth of stacks has stayed.
There is no particular requirement that the compiler map the variables to the stack in descending order but there's a 50/50 chance it will do it that way.
I am trying get a handle on C as I work my way thru Jim Trevor's "Cyclone: A safe dialect of C" for a PL class. Trevor and his co-authors are trying to make a safe version of C, so they eliminate uninitialized pointers in their language. Googling around a bit on uninitialized pointers, it seems like un-initialized pointers point to random locations in memory. It seems like this alone makes them unsafe. If you reference an un-itilialized pointer, you jump to an unsafe part of memory. Period. But the way Trevor talks about them seems to imply that it is more complex. He cites the following code, and explains that when the function FrmGetObjectIndex dereferences f, it isn’t accessing a valid pointer, but rather an unpredictable address — whatever was on the stack when the space for f was allocated.
What does Trevor mean by "whatever was on the stack when the space for f was allocated"? Are "un-initialized" pointers initialized to random locations in memory by default? Or does their "random" behavior have to do with the memory allocated for these pointers getting filled with strange values (that are then referenced) because of unexpected behavior on the stack.
Form *f;
switch (event->eType) {
case frmOpenEvent:
f = FrmGetActiveForm(); ...
case ctlSelectEvent:
i = FrmGetObjectIndex(f, field); ...
}
What does Trevor mean by "whatever was on the stack when the space for f was allocated"?
He means that in most assembly languages, separate instructions are used to reserve space on the stack and to write an initial value inside the newly reserved space. If a C program uses an uninitialized variable, the program will typically at run-time execute the instruction that reserves stack space but no instruction that sets it. When the pointer is used, it will literally contain the bit pattern that was on the stack before space was reserved. In the good cases this will be an invalid address. In the bad cases this will happen to be a valid address, and the effects will be unpredictable.
This is only a typical behavior. From the theoretical point of view, using an indeterminate value is undefined behavior. Much stranger things than simply accessing an invalid address or a valid one can happen (examples with uninitialized data (not addresses) used accidentally or purposely).
Here is the sort of dangers that a restricted subset of C such as Cyclone aims to prevent:
int a, *p;
int main(int c, char **v){
int l, *lp, i;
if (c & 1)
a = l + 1; // danger
if (c & 2)
*lp = 3; // danger
if (c & 4)
{
p = &a;
for (i=0; i<=1; i++)
{
int block_local;
*p = 4; // danger
p = &block_local;
}
}
}
In the last dangerous line, in practice, it is most likely that 4 will be written to variable block_local, but in reality, at the second iteration, p is indeterminate, the program is not supposed to access *p, and it is undefined behavior when it does.
On modern OS's the danger is a core dump. On earlier systems without memory management and possibly memory mapped i/o to external HW the dangers are of completely different magnitude.
can someone explain this to me
main()
{
int *x,y;
*x = 1;
y = *x;
printf("%d",y);
}
when I compile it in gcc how come running this in main function is ok, while running it in different function wont work like the function below?
test()
{
int *x,y;
*x = 1;
y = *x;
printf("%d",y);
}
int *x,y;
*x = 1;
Undefined Behavior. x doesn't point to anything meaningful.
This will be correct:
int *x, y, z;
x = &z;
*x = 1;
y = *x;
or
int *x, y;
x = malloc(sizeof(int));
*x = 1;
y = *x;
//print
free(x);
Undefined behavior is, well, undefined. You can't know how it will behave. It can seem to work, crash, print unpredictable results and anything else. Or it can behave differently on different runs. Don't rely on undefined behavior
Technically, in standardese, you invoke what is called undefined behavior due to using an uninitialized value (the value of the pointer x).
What's going on under the hood is very likely this: your compiler allocates local variables on the stack. Calling functions likely changes the stack pointer, so different function's local variables are at different places on the stack. This in turn makes the value of the uninitialized x be whatever happens to be at that place in the current stack frame. This value can be different, depending on the depth of the chain of functions you called. The actual value can depend on a lot of things, e.g. back to the whole history of processes called before your program started. There's no point in speculating what the actual value might be and what kind of erroneous behavior might possibly ensue. In the C community we refer to undefined behaviour as even having the possibility to make demons fly out of your nose. It might even start WW3 (assuming appropriate hardware is installed).
Seriously, a C programmer worth her money will take extreme care not to invoke undefined behavior.
since x is a pointer, its not containing the int itself, it points to another memory location which holds that value.
I think you assume that declaring a pointer to a value also reserves memory for it... not in C.
If you made the above error in your code, maybe it would be good if I gave you a little bit more graphic representation of what is actually going on in the code... this is a common novice error. The explanation below might seem a bit verbose and basic, but it might help your brain "see" what is actually going on.
Let's begin... if [xxxx] is a value being stored in a few bits in the RAM, and [????] is an unknown value (in physical ram) you can say that that for X to be properly used it should be:
x == [xxxx] -> [xxxx]
x == address of a value (int)
when you write: *x=1 above, you are changing the value of an unknown area of RAM, so you are in fact doing:
x == [????] -> [0001] // address [????] is completely undefined !
In fact, we don't even know IF address [????] is allocated or accessible by your application (this is the undefined part), its possible the address points to anything. Function code, dll address, file handle structure... it all depends on the compiler/OS/application state, and can never be relied on.
so to be able to use a pointer to an int, we must first allocate memory for it, and assign the address of that memory to x, ex:
int y; // allocate on the stack
x = &y; // & operator means, *address* of"
or
x = malloc(sizeof(int)); // in 'heap' memory (often called dynamic memory allocation)
// here malloc() returns the *address* of a memory space which is at least large enough
// to store an int, and is known to be reserved for your application.
at this point, we know that x holds a proper memory address so we'll just say it's currently set to [3948] (and contains an unknown value).
x == [3948] -> [????]
Using the * operator, you dereference the pointer address (i.e. look it up), to store a value AT that address.
*x = 1;
means:
x == [3948] -> [0001]
I hope this helps