Playing with pointer in c language - c

Could we point and address specific place in memory using pointer in c language?
Then modify it from another file (ANOTHER PROGRAM) and view it from any where.
Like :
Modifying it :
#include<stdio.h>
void main(){
int *p;
p= 12345678;
scanf("%d",p);
}
Viewing it :
#include<stdio.h>
void main(){
int *p;
p= 12345678;
printf("%d", *p);
}

No. Each process in your operating system has its own address space.
Processes can communicate, using the channels provided by the operating system.
Look into IPC, aka inter process communication, if you're interested in knowing more about it.

What about const volatile pointer (which will be pointing to some memory)? If I'm not wrong it will point to some memory it won't change during first program (also you will not be allowed to modify this memory) but that memory can be modified by another program/process etc.
EDIT:
Just to clarify if we use const volatile pointer it will do two things.
In program it won't allow us to change it value after initialisation
More important volatile keyword will disallow some compiler optimisations on readings and will always reload from memory each time it is accessed by the program. This dramatically reduces the possible optimisations. However, when the state of an object can change unexpectedly, it is the only way to ensure predictable program performance.

Related

Are memory addreses portable in C?

Say we have program 1...
./program1
int main(int argc, char *argv[])
{
int *i;
*i = 10;
printf("%lld", i);
return 0;
}
Now program 2...
./program2 program1output 10
int main(int argc, char *argv[])
{
int *t;
t = (int*)atoll(argv[1]);
*t = atoi(argv[2]);
return 0;
}
Will this work? Can you share memory addresses between different programs?
This behavior is not defined by the C standard. On any general-purpose multi-user operating system, each process is given its own virtual address space. All of the memory assigned to a process is separate from the memory assigned to other processes except for certain shared memory:
Read-only data may be shared between processes, especially the instructions and constant data of two processes running the same executable and the instructions and constant data of shared libraries. That data may have the same address in different processes or different addresses (depending on various factors, including whether the code is position-independent and whether address space layout randomization is in use).
Some operating systems also map system-wide shared data into processes by default.
Memory may be shared between processes by explicit request of those processes to map shared memory segments. Those segments may or may not appear at the same virtual address in the different processes. (A request to map shared memory may request a certain address, in which case different processes could arrange to use the same address, or it could let the mapping software choose the address, in which case different processes cannot rely on receiving the same address assignment.)
In a special-purpose operating system, different processes could share one address space.
Supplement
This is not correct code:
int *i;
*i = 10;
The declaration int *i; defines i to be a pointer but does not assign it a value. Then using *i is improper because it attempts to refer to where i points, but i has not been assigned to point to anything.
To define an int and make its address visible in output, you could define int i; and then print &i.
This is not the proper way to print an address:
printf("%lld", i);
To print an address, cast it to void * and format it with %p. The result of the formatting is implementation-defined:
printf("%p", (void *) &i);
This is not a good way to reconstruct an address:
int *t;
t = (int*)atoll(argv[1]);
As with printf, the type should be void *, and there are problems attempting the conversion with atoll. The C standard does not guarantee it will work; the format produced by printing with %p might not be a normal integer format. Instead, use the %p specifier with sscanf:
void *temp;
if (1 != sscanf(argv[1], "%p", &temp))
exit(EXIT_FAILURE);
int *t = temp;
When the address comes from other process, the behavior of the sscanf conversion is not defined by the C standard.
In principal, an application operates on its own/private memory. There are ways of sharing memory among different processes, but this requires special mechanism to overcome above mentioned "principal" (memory mapped files, for example). Have a short look at, for example, this article on sharing memory.
In your case, program one will have ended and its memory is not available any more; and the way you access it is definitely not one of the "special mechanisms" necessary to access shared memory:
Though an integer vale may be converted to a pointer value, accessing this pointer is only valid if the integer value has originally been converted from a pointer to a valid object. This is not the case in your example, since the integral value calculated in t = (int*)atoll(argv[1]); never pointed to a valid object in the current program.
In general, memory addresses are tied to processes because each process may have its own memory space. So, the addresses are virtual addresses rather than physical addresses, which means they are references to a location in the process's memory space rather than references to a location on a chip.
(Not all environments have virtual memory. For example, an embedded system might not.)
If you have two programs running in the same process, a pointer can be passed between them. For example, a main program can pass a pointer to a dynamically linked library it loads.

how to access memory allocated to different process? [duplicate]

This question already has answers here:
change a pointer of address of another application
(4 answers)
Closed 9 years ago.
I have edited 1.c as below.
#include<stdio.h>
int x=100;
int main(void)
{
printf("%p",&x);
while(1);
return 0;
}
Then I opened Command Prompt and run this program and got Output 00402000 while program still running. Now I run 2.c
#include<stdio.h>
int main(void)
{
int *p=(int *)0x00402000;
printf("%d",*p);
return 0;
}
in another instance of command prompt and got output -1, I expect 100 which is in location 00402000. please explain why is this behavior?
First and foremost, let me say that in modern operating systems, the address values that your program sees (like that 0x00402000) are not physical addresses. They are virtual addresses, they're private to the owning process (i. e. make no sense or mean something else in other processes), and are mapped to physical addresses via a CPU-based mechanism ("the paging unit") that only OS has control over.
If you want to share a variable between different processes, there's a mechanism called shared memory. Read up on it. The relevant APIs are CreateFileMapping with the the first parameter being INVALID_HANDLE_VALUE, MapViewOfFile, OpenFileMapping. There are other ways of interprocess communication, too.
If you want to read process' memory without that process' explicit cooperation, you need to read up on debugging API. This is a much trickier job than using shared memory.
What you've coded, by the way, is a classic undefined behavior.
To demo the address space concept, modify your second example to:
#include<stdio.h>
int y = 101;
int main(void)
{
int *p=(int *)0x00402000; // hope this works??
printf("%d",*p);
printf("%p", p); // print value of p to ensure correct assignment
return 0;
}
It probably/might print "101" !! This is because the OS treats each address space the same. So the, global var for an int regardless of its name probably gets allocated to location 0x004002000.
Appears to be undefined behavior. Since a user's process is only allowed to access memory which has been assigned to it.
So as you try to access the memory about the address, your assigning an invalid address, and you are running into undefined behavior.

Why does a program accessing illegal pointer to pointer not crash?

A program accessing illegal pointer to pointer does not crash with SIGSEGV. This is not a good thing, but I’m wondering how this could be and how the process survived for many days in production. It is bewildering to me.
I have given this program a go in Windows, Linux, OpenVMS, and Mac OS and they have never complained.
#include <stdio.h>
#include <string.h>
void printx(void *rec) { // I know this should have been a **
char str[1000];
memcpy(str, rec, 1000);
printf("%*.s\n", 1000, str);
printf("Whoa..!! I have not crashed yet :-P");
}
int main(int argc, char **argv) {
void *x = 0; // you could also say void *x = (void *)10;
printx(&x);
}
I am not surprised by the lack of a memory fault. The program is not dereferencing an uninitialized pointer. Instead, it is copying and printing the contents of memory beginning at a pointer variable, and the 996 (or 992) bytes beyond it.
Since the pointer is a stack variable, it is printing memory near the top of stack for a ways down. That memory contains the stack frame of main(): possibly some saved register values, a count of program arguments, a pointer to the program arguments, a pointer to a list of environment variables, and a saved instruction register for main() to return, usually in the C runtime library startup code. In all implementations I have investigated, the stack frames below that has copies of the environment variables themselves, an array of pointers to them, and an array of pointers to the program arguments. In Unix environments (which you hint you are using) the program argument strings will be below that.
All of this memory is "safe" to print, except some non-printable characters will appear which might mess up a display terminal.
The chief potential problem is whether there is enough stack memory allocated and mapped to prevent a SIGSEGV during access. A segment fault could happen if there is too little environment data. Or if the implementation puts that data elsewhere so that there are only a few words of stack here. I suggest confirming that by cleaning out the environment variables and re-running the program.
This code would not be so harmless if any of the C runtime conventions are not true:
The architecture uses a stack
A local variable (void *x) is allocated on the stack
The stack grows toward lower numbered memory
Parameters are passed on the stack
Whether main() is called with arguments. (Some light duty environments, like embedded processors, invoke main() without parameters.)
In all mainstream modern implementations, all of these are generally true.
Illegal memory access is undefined behaviour. This means that your program might crash, but is not guaranteed to, because exact behaviour is undefined.
(A joke among developers, especially when facing coworkers that are careless about such things, is that "invoking undefined behaviour might format your hard drive, it's just not guaranteed to". ;-) )
Update: There's some hot discussion going on here. Yes, system developers should know what actually happens on a given system. But such knowledge is tied to the CPU, the operating system, the compiler etc., and generally of limited usefulness, because even if you make the code work, it would still be of very poor quality. That's why I limited my answer to the most important point, and the actual question asked ("why doesn't this crash"):
The code posted in the question does not have well-defined behaviour, but that does just mean that you can't really rely on what it does, not that it should crash.
If you dereference an invalid pointer, you are invoking undefined behaviour. Which means, the program can crash, it can work, it could cook some coffee, whatever.
When you have
int main(int argc, char **argv) {
void *x = 0; // you could also say void *x = (void *)10;
printx(&x);
}
You are declaring x as a pointer with value 0, and that pointer lives in the stack since it's a local variable. Now, you are passing to printx the address of x, which means that with
memcpy(str, rec, 1000);
you are copying data from above the stack (or in fact from the stack itself), to the stack (because the stack pointer address decreases on each push). The source data is likely to be covered by the same page table entry as you are copying just 1000 bytes, so you get no segmentation fault. However, ultimately, as already written, we are talking about undefined behavior.
It would be crashed with great probability if you write to unacceed area. But you are reading, it can be ok. But the behaviour will be still undefined.

Volatile keyword in C [duplicate]

This question already has answers here:
Why is volatile needed in C?
(18 answers)
Closed 9 years ago.
I am writing program for ARM with Linux environment. its not a low level program, say app level
Can you clarify me what is the difference between,
int iData;
vs
volatile int iData;
Does it have hardware specific impact ?
Basically, volatile tells the compiler "the value here might be changed by something external to this program".
It's useful when you're (for instance) dealing with hardware registers, that often change "on their own", or when passing data to/from interrupts.
The point is that it tells the compiler that each access of the variable in the C code must generate a "real" access to the relevant address, it can't be buffered or held in a register since then you wouldn't "see" changes done by external parties.
For regular application-level code, volatile should never be needed unless (of course) you're interacting with something a lot lower-level.
The volatile keyword specifies that variable can be modified at any moment not by a program.
If we are talking about embedded, then it can be e.g. hardware state register. The value that it contains may be modified by the hardware at any unpredictable moment.
That is why, from the compiler point of view that means that compiler is forbidden to apply optimizations on this variable, as any kind of assumption is wrong and can cause unpredictable result on the program execution.
By making a variable volatile, every time you access the variable, you force the CPU to fetch it from memory rather than from a cache. This is helpful in multithreaded programs where many threads could reuse the value of a variable in a cache. To prevent such reuse ( in multithreaded program) volatile keyword is used. This ensures that any read or write to an volatile variable is stable (not cached)
Generally speaking, the volatile keyword is intended to prevent the compiler from applying any optimizations on the code that assume values of variables cannot change "on their own."
(from Wikipedia)
Now, what does this mean?
If you have a variable that could have its contents changed at any time, usually due to another thread acting on it while you are possibly referencing this variable in a main thread, then you may wish to mark it as volatile. This is because typically a variable's contents can be "depended on" with certainty for the scope and nature of the context in which the variable is used. But if code outside your scope or thread is also affecting the variable, your program needs to know to expect this and query the variable's true contents whenever necessary, more than the normal.
This is a simplification of what is going on, of course, but I doubt you will need to use volatile in most programming tasks.
In the following example, global_data is not explicitly modified. so when the optimization is done, compiler thinks that, it is not going to modified anyway. so it assigns global_data with 0. And uses 0, whereever global_data is used.
But actually global_data updated through some other process/method(say through ptrace ). by using volatile you can force it to read always from memory. so you can get updated result.
#include <stdio.h>
volatile int global_data = 0;
int main()
{
FILE *fp = NULL;
int data = 0;
printf("\n Address of global_data:%x \n", &global_data);
while(1)
{
if(global_data == 0)
{
continue;
}
else if(global_data == 2)
{
;
break;
}
}
return 0;
}
volatile keyword can be used,
when the object is a memory mapped io port.
An 8 bit memory mapped io port at physical address 0x15 can be declared as
char const ptr = (char *) 0x15;
Suppose that we want to change the value at that port at periodic intervals.
*ptr = 0 ;
while(*ptr){
*ptr = 4;//Setting a value
*ptr = 0; // Clearing after setting
}
It may get optimized as
*ptr = 0 ;
while(0){
}
Volatile supress the compiler optimization and compiler assumes that tha value can
be changed at any time even if no explicit code modify it.
Volatile char *const ptr = (volatile char * )0x15;
Used when the object is a modified by ISR.
Sometimes ISR may change tha values used in the mainline codes
static int num;
void interrupt(void){
++num;
}
int main(){
int val;
val = num;
while(val != num)
val = num;
return val;
}
Here the compiler do some optimizations to the while statement.ie the compiler
produce the code it such a way that the value of num will always read form the cpu
registers instead of reading from the memory.The while statement will always be
false.But in actual scenario the valu of num may get changed in the ISR and it will
reflect in the memory.So if the variable is declared as volatile the compiler will know
that the value should always read from the memory
volatile means that variables value could be change any time by any external source. in GCC if we dont use volatile than it optimize the code which is sometimes gives unwanted behavior.
For example if we try to get real time from an external real time clock and if we don't use volatile there then what compiler do is it will always display the value which is stored in cpu register so it will not work the way we want. if we use volatile keyword there then every time it will read from the real time clock so it will serve our purpose....
But as u said you are not dealing with any low level hardware programming then i don't think you need to use volatile anywhere
thanks

Can an address be assigned to a variable in C?

Is it possible to assign a variable the address you want, in the memory?
I tried to do so but I am getting an error as "Lvalue required as left operand of assignment".
int main() {
int i = 10;
&i = 7200;
printf("i=%d address=%u", i, &i);
}
What is wrong with my approach?
Is there any way in C in which we can assign an address we want, to a variable?
Not directly.
You can do this though : int* i = 7200;
.. and then use i (ie. *i = 10) but you will most likely get a crash. This is only meaningful when doing low level development - device drivers, etc... with known memory addreses.
Assuming you are on an x86-type processer on a modern operating system, it is not possible to write to aribtray memory locations; the CPU works in concert with the OS to protect memory so that one process cannot accidentally (or intentionally) overwrite another processes' memory. Allowing this would be a security risk (see: buffer overflow). If you try to anyway, you get the 'Segmentation fault' error as the OS/CPU prevents you from doing this.
For technical details on this, you want to start with 1, 2, and 3.
Instead, you ask the OS to give you a memory location you can write to, using malloc. In this case, the OS kernel (which is generally the only process that is allowed to write to arbitrary memory locations) finds a free area of memory and allocates it to your process. The allocation process also marks that area of memory as belonging to your process, so that you can read it and write it.
However, a different OS/processor architecture/configuration could allow you to write to an arbitrary location. In that case, this code would work:
#include <stdio.h>
void main() {
int *ptr;
ptr = (int*)7000;
*ptr = 10;
printf("Value: %i", *ptr);
}
C language provides you with no means for "attaching" a name to a specific memory address. I.e. you cannot tell the language that a specific variable name is supposed to refer to a lvalue located at a specific address. So, the answer to your question, as stated, is "no". End of story.
Moreover, formally speaking, there's no alternative portable way to work with specific numerical addresses in C. The language itself defines no features that would help you do that.
However, a specific implementation might provide you with means to access specific addresses. In a typical implementation, converting an integral value Ato a pointer type creates a pointer that points to address A. By dereferencing such pointer you can access that memory location.
Not portably. But some compilers (usually for the embedded world) have extensions to do it.
For example on IAR compiler (here for MSP430), you can do this:
static const char version[] # 0x1000 = "v1.0";
This will put object version at memory address 0x1000.
You can do in the windows system with mingw64 setup in visual studio code tool, here is my code
#include<stdio.h>
int main()
{
int *c;
c = (int *)0x000000000061fe14; // Allocating the address 8-bit with respect to your CPU arch.
*c = NULL; // Initializing the null pointer for allocated address
*c = 0x10; // Assign a hex value (you can assign integer also without '0x')
printf("%p\n",c); // Prints the address of the c pointer variable
printf("%x\n",*c); // Prints the assigned value 0x10 -hex
}
It is tested with mentioned environment. Hope this helps Happy coding !!!
No.
Even if you could, 7200 is not a pointer (memory address), it's an int, so that wouldn't work anyway.
There's probably no way to determine which address a variable will have. But as a last hope for you, there is something called "pointer", so you can modify a value on address 7200 (although this address will probably be inaccessible):
int *i = (int *)7200;
*i = 10;
Use ldscript/linker command file. This will however, assign at link time, not run time.
Linker command file syntax depends largely on specific compiler. So you will need to google for linker command file, for your compiler.
Approximate pseudo syntax would be somewhat like this:
In linker command file:
.section start=0x1000 lenth=0x100 myVariables
In C file:
#pragma section myVariables
int myVar=10;
It's not possible, maybe possible with compiler extensions. You could however access memory at an address you want (if the address is accessible to your process):
int addr = 7200;
*((int*)addr) = newVal;
I think '&' in &a evaluates the address of i at the compile time which i think is a virtual address .So it is not a Lvalue according to your compiler. Use pointer instead

Resources