Why address of a variable change after each execution in C? - c

int i=10;
printf("Address of i = %u",&i);
Output:
Address if i = 3220204848
Output on re-execution:
Address of i = 3216532594
I get a new address of i each time I execute the program. What does this signify?

It signifies that your program is being loaded a different (virtual) address each time you run it. This is a feature called Address Space Layout Randomization (ASLR) and is a feature of most modern operating systems.

That's how operating systems work. When you declare a variable, you're asking the underlying systems to allocate a memory block (address) to store that data (or a pointer to another block if you're dealing with pointers, but here you've got a primitive, so it's just data being stored). The program doesn't care where the memory is, just that it exists, because it knows how to keep track of whatever it's given.
As the programmer, this really isn't that big of a deal unless you're doing some incredibly low-level work. The hardest part of this to really grasp, for most people, is that when you work with pointers, you can't equate things the same way you can primitives, because pointers consider their values (when using == as an equator) to be their memory addresses.

Disable ASLR using:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
You will always see the same address.

At the time of c program execution another processes are running.While executing a code again you will allocate new address previously allocated address will be allocate for another process.

Related

Address of environment variable changes on program call [duplicate]

int i=10;
printf("Address of i = %u",&i);
Output:
Address if i = 3220204848
Output on re-execution:
Address of i = 3216532594
I get a new address of i each time I execute the program. What does this signify?
It signifies that your program is being loaded a different (virtual) address each time you run it. This is a feature called Address Space Layout Randomization (ASLR) and is a feature of most modern operating systems.
That's how operating systems work. When you declare a variable, you're asking the underlying systems to allocate a memory block (address) to store that data (or a pointer to another block if you're dealing with pointers, but here you've got a primitive, so it's just data being stored). The program doesn't care where the memory is, just that it exists, because it knows how to keep track of whatever it's given.
As the programmer, this really isn't that big of a deal unless you're doing some incredibly low-level work. The hardest part of this to really grasp, for most people, is that when you work with pointers, you can't equate things the same way you can primitives, because pointers consider their values (when using == as an equator) to be their memory addresses.
Disable ASLR using:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
You will always see the same address.
At the time of c program execution another processes are running.While executing a code again you will allocate new address previously allocated address will be allocate for another process.

Access process memory directly

simple question:
Is it possible, and how is it possible, to acess the Virtual Memory of my program directly?
To be specific,
instead of typing
int someValue = 5;
can I do something like this:
VirtualMemory[0x0] = (int)5;
I'm just asking because I want the values to be stored next to each other to get a nice and small memory map.
When I look into assembler basics, the processor stores values directly after each other and I was wondering how to do so in c.
Thanks for all of your replies.
Cheers,
Lucky
Not exactly, because in the source code you don't know which memory address your program is going to be "loaded into". So all memory addresses in the program are encoded in an "offset from the start of program" type manner.
Part of the "process loader"'s responsibility in copying the program into memory is to add the "base offset pointer" to all the other offesets, so all the "names" describing memory addresses refer to actual memory addresses instead of "offsets from the beginning of the program".
That's generally a good thing, as if they were encoded directly, two programs that needed the same set of addresses couldn't be run at the same time without corrupting each other's shared memory. In addition, loading a program into a different starting address would not be possible, as walking outside of the memory of your program (nearly guaranteed if you relocate the program without rewriting the memory address references) is going to raise a segfault in the operating system's memory management monitors.
Also you need a name to start at, and this means that the offsets are bound to the variable names. Generally it is much easier to do fishing around in the heap based off of an alloc'd item than it is to truly find the start of the program loaded in memory (because the C programming language doesn't really capture that address into a in-language variable name, and the layout is somewhat system dependent).

Declare a pointer to an integer at address 0x200 in memory

I have a couple of doubts, I remember some where that it is not possible for me to manually put a variable in a particular location in memory, but then I came across this code
#include<stdio.h>
void main()
{
int *x;
x=0x200;
printf("Number is %lu",x); // Checkpoint1
scanf("%d",x);
printf("%d",*x);
}
Is it that we can not put it in a particular location, or we should not put it in a particular location since we will not know if it's a valid location or not?
Also, in this code, till the first checkopoint, I get output to be 512.
And then after that Seg Fault.
Can someone explain why? Is 0x200 not a valid memory location?
In the general case - the behavior you will get is undefined - everything can happen.
In linux for example, the first 1GB is reserved for kernel, so if you try to access it - you will get a seg fault because you are trying to access a kernel memory in user mode.
No idea how it works in windows.
Reference for linux claim:
Currently the 32 bit x86 architecture is the most popular type of
computer. In this architecture, traditionally the Linux kernel has
split the 4GB of virtual memory address space into 3GB for user
programs and 1GB for the kernel.
Adding to what #amit wrote:
In windows it is the same. In general it is the same for all protected-mode operating systems. Since DOS etc. are no longer around it is the same with all systems except kernel-mode (km-drivers) and embedded systems.
The operating system manages which memory-pages you are allowed to write to and places markers that will make the cpu automatically raise access-violations if some other page is written to.
Up until the "checkpoint", you haven't accessed memory location 0x200, so everything works fine.
There I'd a local variable x in the function main. It is of type "pointer to int". x is assigned the value 0x200, and then that value is printed. But the target of x hasn't been accessed, so up to this point it doesn't matter whether x holds a valid memory address or not.
Then scanf tries to write to the memory address you passed in, which is the 0x200 stored in x. Then you get a seg fault, which is certainly sac possible result of trying to write to an arbitrary memory address.
So what are your doubts? What makes you think that this might work, when you come across this code that clearly doesn't?
Writing to a particular memory address might work under certain conditions, but is extremely unlikely to in general. Under all modern OSes, normal programs do not have control over their memory layout. The OS decides where initial things like the program's code, stack, and globals go. The OS will probably also be using some memory space, and it is not required to tell you what it's using. Instead you ask for memory (either by making variables or by calling memory allocation routines), and you use that.
So writing to particular addresses is very very likely to get either memory that hasn't been allocated, or memory that is being used for some other purpose. Neither of those is good, even if you do manage to hit an address that is actually writable. What if you clobber sundry some piece of data used by one of your program's other variables? Or some other part of your program clobbers the value you just wrote?
You should never be choosing a particular hard-coded memory address, you should be using an address of something you know is a variable, or an address you got from something like malloc.

reading a arbitary memory location making the program crash

I am trying to read the value at random memory location using the following c code
main()
{
int a,*b;
printf("enter the value of a");
scanf("%d",&a);
b=a;
printf("%d\n%d\n",a,*b);
getch();
}
But the program is crashing when some negative values or even when zero is entered in place of variable a through scanf.
What I am doing wrong? Does the pointers dont have negative values?
The thing is that as you are probably running on a modern, full service operating system and it provides a more complicated abstract machine than the one described in most intro to c programming books.
In particular, there are OS imposed restrictions on access to arbitrary addresses. You don't notice this when you look at addresses associated with standard variables because you do have permission to use the stack and the data segment, and the alloc family of functions takes care of making sure that you have permission to access the parts of the heap that they hand you.
So, what you are doing is accessing memory for which you do not have permission, which results in a failure called a "segmentation fault" on most OS, and that abruptly ends your program.
What can you do about it?
Allocate a big block on the heap, by calling char *p = malloc(1000000); and then find the starting and ending addresses with something like printf("start:\t%p\nend\t%p\n",(void*)p,(void*)(p+1000000)); and only entering numbers in that range.
Note that the %p specifier print specifier outputs in hexadecimal, so you probably want to enter address in the same base. The standard library function strtol will be helpful in that regard.
A more sophisticated approach would be to use your OS's API to request access permission for arbitrary address, but for some values the OS is likely to simply refuse.
I see some confusion here over just want a pointer is.
First, you ask the user for a value. This is fine. Then you assign that value as the location of the pointer b. This MAY be fine but likely not.
Think for a moment, what does *(-500) mean? What would *(0) mean?
In general you can never just take user input and use it without first checking it or manipulating it. This is one place where security breaches come from.
If you want to experiment with dereferencing memory, just hard code some values at first. Load the program up in a debugger and see what happens.
int c;
b = 500;
c = *b; // what happens?
b = 0;
c = *b; // what happens?
b = -100;
c = *b; // what happens?
Let me greatly oversimplify for you...
In almost all modern computers, with most operating systems, very little of the memory in the machine is directly addressable by your program. You can't take a pointer, point it at something, and try to read it. It will almost always fail.
There are generally three things that will go wrong:
The memory doesn't exist where you're pointing. Pointers can hold large range of values, and not all of them mean anything. It's like a house number in a postal address. Technically, you can put anything you want on the envelope. Only some are valid.
The memory exists, but isn't yours. The vast majority of memory in the computer is "owned" by the operating system and if you touch it, it will terminate your program. This is for your safety.
The memory you're trying to address is valid, in the right range, but not quite the right type. From the earlier example, you might have a reasonable house number but there's no house at that location. Or the address is really an apartment and just a number won't do.
In an old 8-bit computer from the 1980's with a full 64k of memory, you could just read any location you wanted to and it would be fine. Not so much anymore.
In theory, you have permissions to read from any address within your virtual address space (e.g. 0 to 0xFFFFFFFF on a 32-bit machine).
0 and negative numbers are not a problem - once you assign them to pointers, they are casted to non-negative values.
In practice, it won't work. OS will protect itself (and you) from this - it won't let you read from address that doesn't really belong to you.
That is, if you haven't allocated the memory page and haven't write something there, OS won't let you to read from there.
Moreover, you don't really own the whole address space - lower part of it is owned by kernel et al., so OS won't let you access it.
Pointers are exclusively positive from what I have heard. 0 (the NULL pointer) is guaranteed not to point at anything and will cause the program to halt. Further, operatings systems (even hardware if I remember correctly) provide memory protection. This is why programs used to be able to crash each other but this is now much less common. When you program runs, the OS decides what memory it has access to and will throw a segfault if you try to access memory that isn't yours.
Then again, perhaps you just wanted b = &a? This would make b point to the same place as a exists and so, when you *b it would equate to the value stored in a.
As i see you declare b as pointer, hence it is wrong to do a=b. You will get segmentation fault. Pointers only shows to pointers not to values of integers, floats or chars.
Alternatively you could do b = &a, which means that b shows to the memory address of a. So you could print then the value stored in the a.

assigning a value to the address

I tried the below program to make the pointer to point to a particular address and to store a value in that address.When i make the pointer to contain the value for the assigned address i'm getting a run time error asking me to close the program.
Is it not possible to assign a value to the address 0x6778.why is it so? In what situations does this needed? Please help me understand.
int *p=(int*)0x6778;
printf("The address is:%x",p);
When tried to do *p=1000 i am getting the error.
There are many reasons why this could give you an error:
The address 0x6778 might not be part of this process's virtual memory -- it might not really "exist". You could read more about virtual memory, but basically addresses don't refer directly to physical bytes -- they have to be translated in a table, and that table might not have an entry for your address.
If it is mapped, it might be on a read-only page
If it's mapped and writable, it might corrupt some other part of your program, causing a segfault soon after.
In general, you probably can't write to an arbitrary address in a user-level application. Of course, if you're running a kernel or embedded system, ignore this answer, as it totally does not apply ;-)
That address is likely not in your process's address space, so your program receives an exception from the operating system when you try to access it. You shouldn't be trying to use specific memory locations to store things... rather, use malloc for dynamic allocation, or put things on the stack.
int *p=(int*)0x6778;
To do this, the address location 0x6778 should be a valid address location in first place.
An Address space gets allocated to every process, Your program runs in an particular process, If an program tries to access an address location beyond its address space then it will crash. Seems that is happening in your case.
Unless, you are sure that an virtual address location is valid for use by your program DO NOT access the address locations explicitly, let the compiler put the types in address space allocated to your process and return it back to you. To do that, the simplest way is to just make use of local variables with automatic storage or use malloc for dynamic allocations.

Resources