I have shared Memory like this
struct MEMORY {
char * type;
int number;
}
now in code I make it shared everything works probably but other process can't see what pointer points to how can I use pointer in shared memory?
You need to make sure that the shared memory is attached at the same address in the address space of all the processes. Otherwise, as you can imagine, the pointer values end up meaning different things in different processes.
What are you using for shared memory? mmap or shm? It is the first argument in the mmap call.
If you cannot assure same address space in all processes, the other way to go is to us offsets only. Each process simply offsets from the base address where the shared memory is attached.
EDIT: Ah ... maybe what you are saying is that "char* type" is some arbitrary pointer. Remember that the other processes can only see what is in the shared memory. All other memory locations (pointer values) are inaccessible. So, for this pointer to work, it needs to be to something that is in shared memory, not just any arbitrary pointer. That, and you need to assure that the shared memory is attached at the same address in all processes.
Related
I wrote this code so I can see the address of variable foo.
#include <stdio.h>
#include <stdlib.h>
int main(){
char* foo=(char*) malloc(1);
*foo='s';
printf(" foo addr : %p\n\n" ,&foo);
int pause;
scanf("%d",&pause);
return 0;
}
Then pause it and use the address of foo in here:
#include <stdio.h>
int main(){
char * ptr=(char *)0x7ffebbd57fc8; //this was the output from the first code
printf("\n\n\n\n%c\n\n\n",*ptr);
}
but I keep getting segmentation fault. Why is this code not working?
This is not a C question/problem but a matter of runtime support. On most OS programs run in a virtual environment, especially concerning their memory space. In such case memory is a virtual memory which means that when a program access a given address x the real (physical) memory is computed as f(x). f is a function implemented by the OS to ensure that a given process (object which represent the running of a code in the OS) have its own reserved memory separated from memory dedicated to other processes. This is called virtual memory.
Oups, your problem is not related to C language, but really depends of the OS, if any.
First let us read it from a pure C language point of view:
char * ptr=(char *)0x7ffebbd57fc8;
your are converting an unsigned integer to a char *. As you get the integer value from the other program, you can be sure that is has an acceptable range, so you indeed get a pointer pointing to that address. As it is a char * pointer, you can use it to read the byte representation of any object that will lie at that address. Still fine until there. But common systems use virtual addresses and limit each process to access only its own pages, so by default a process cannot access the memory of another process. In addition, with the common usage of virtual memory, there are no reasons that any two non kernel processes share common addresses. Exceptions for real addresses are:
real memory OS (MS/DOS and derivatives like FreeDOS, CP/M, and other anthic systems)
kernel mode: the kernel can access the whole memory of the system - who could load your program?
special functions: some OS provide special API to let one process read the memory of another one (Windows does), but it not as simple as directly reading an address...
As I assume that you are not in any of the first two cases, nothing is mapped at that address from the current process, hence the error.
On systems use virtual memory, you have a range of logical addresses that are available to user processes. These address ranges are subdivided into units called PAGES whose size depends upon the processor (512b to 1MB).
Pages are not valid until they are mapped into the process. The operating system will have system calls that allow the application to map pages. If you try to access a page that is not valid you get some kind of exception.
While the operating system only allocates memory pages, applications are used to calls, such as malloc(), that allocate memory blocks of arbitrary sizes.
Behind the scenes, malloc() is mapping pages (ie making them valid) to create a pool of memory that is uses to return small amounts of memory.
When you omit your malloc(), the memory is not being mapped.
Note that each process has its own range of logical addresses. One process's page containing 0x7ffebbd57fc8 is likely to be mapped to a different physical page frame than another process's 0x7ffebbd57fc8. If that were not the case, one user could muck with another. (There is always a range of addresses shared by all processes but this is can only be accessed in kernel mode.)
Your problem is further complicated by the fact that many systems these days randomly map processes to different locations in the logical address space. On such systems you could run your first program multiple times and get different addresses.
Why is this code not working?
You would need to call the system service on your operating system that maps memory into the process and make the page containing 0x7ffebbd57fc8 accessible.
I am using C on Linux, and allocating 2 shared memory segments.
The first segment is created in a main program, then I call a subprocess and create the second segment.
In the subprocess, I place the address of the second segment in a pointer I set aside in the first segment.
Upon returning to the main program, when I attach to the second segment and compare the pointers (the one returned from shmat, and the one previously stored by the subprocess) I find they are different.
Is this expected?
Thanks, Mark.
Yes, this is expected. Mapping to a common address in the virtual space of the two processes would be a very constraining limitation. Among others, the memory manager would have to know simultaneously which processes are willing to map, so that it finds a common free area. This would defeat the very principle of virtual memory (every process sees a blank address space), and cause configurations impossible to arbitrate.
Sharing at common addresses is indeed possible, but only makes sense when the mapping is to some reserved section of the address space, so that it doesn't get mapped elsehow.
Am I printing it wrong?
#include <stdio.h>
#include <stdlib.h>
int
main( void )
{
int * p = malloc(100000);
int * q;
printf("%p\n%p\n", (void *)p, (void *)q);
(void)getchar(); /* to run several instances at same time */
free(p);
return 0;
}
Whether I run it sequentially or in multiple terminals simultaneously, it always prints "0x60aa00000800" for p (q is different, though).
EDIT: Thanks for the answers, one of the reasons I was confused was because it used to print a different address each time. It turns out that a new compiler option I started using, -fsanitize=address, caused this change. Whoops.
The value of q is uninitialized garbage, since you never assign a value to it.
It's not surprising that you get the same address for p each time you run the program. That address is almost certainly a virtual address, so it applies only to the memory space of the currently running program (process).
Virtual address 0x60aa00000800 as seen from one program and virtual address 0x60aa00000800 as seen from another program are distinct physical addresses. The operating system maps virtual addresses to physical addresses, and vice versa, so there's no conflict. (If different programs could read and write the same physical memory, it would be a security nightmare.)
It also wouldn't be surprising if they were different each time. For example, some operating systems randomize stack addresses to prevent some code exploits. I'm not sure whether heap addresses are also randomized, but they certainly could be.
https://en.wikipedia.org/wiki/Virtual_memory
This behavior is not entirely surprising. The malloc operation is simply returning a pointer to user addressable + allocated memory in the process. It's completely reasonable for the first memory request of the same size to return the same address through different invocations of a process
The behavior for q doesn't contradict this. You have given q no value hence it gets whatever the last value written to that portion of the stack was. It's unsurprising that undefined behavior would be different through different invocations of the same process (after all, it's undefined)
Your code is fine.
The same code, and the same algorithm for obtaining memory with malloc() is run each time, so there's no reason the addresses should be different.
Some malloc implementations could randomize the start of memory allocations, yours does not.
This is because of virtual memory. The physical memory address for memory of q is different, but your operating system provides each process with a virtual view of memory, mapping different physical memory addresses to the same virtual addresses in your processes. So all processes have a similar view of the memory (and cannot see the memory of other processes)
Heap allocators are not required to provide distinct / unique addresses each time you run the program. There is no guarantee either way on this, but it's entirely reasonable for an implementation of malloc() to have deterministic behavior and give you the same pointer each time you run the program.
The stack, on the other hand, usually is (but is not required to be) located at a different address. This is a protection measure against buffer-overflow exploits. By making the stack location non-deterministic, they make it more difficult for an attacker to inject direct memory addresses of code via buffer-overflow attack.
Finally note that all pointers in a program are virtual memory addresses, not physical addresses. So even though two concurrent processes might have the same memory address in a pointer, those two processes still have distinct memory in separate areas of physical memory. The operating system takes care of this via its virtual memory manager and page translation. Each process has its own virtual address space, various pieces of which are mapped transparently by the OS to physical memory as needed.
I have a structure which looks like:
typedef struct shared_data_t
{
char *key;
char *message;
}shared_data;
I need to share this structure with another unrelated process. I am using POSIX shared memory with shm_open()/mmap() to achieve this. However, my target process is not getting the shared data and its dieing with SIGSEGV, which is obvious. It will be great if someone help me on this, specially what happens while sharing pointers between two processes with shared memory (with shm_open and mmap).
For a structure like,
typedef struct shared_data_t
{
char key[8];
char message[32];
}shared_data;
it works all fine!
There is a note about this in the Linux man page for shmat:
Using shmat() with shmaddr equal to NULL is the preferred, portable way
of attaching a shared memory segment. Be aware that the shared memory
segment attached in this way may be attached at different addresses in
different processes. Therefore, any pointers maintained within the
shared memory must be made relative (typically to the starting address
of the segment), rather than absolute.
The struct contains two pointers, for key and message. They have values such as 0x1000 and 0x1040. Your first process maps shared memory, say at address 0x7000. It copies the struct into shared memory. The second process maps the same shared memory, say at address 0x9000. It reads the struct. Then it uses the pointers, which causes it to look for key and message at addresses 0x1000 and 0x1040. But they are not at those addresses in the memory of the second process. So the second process fails.
To fix this, you must arrange for key and message to be in shared memory, and you must either arrange for them to be at the same address in both processes (by telling mmap exactly where you want to map memory, not letting the system pick the address) or you must include information in the shared memory about how to locate key and message. This is often done by using offsets instead of pointers. That is, instead of having pointers to char in the struct, have offsets (possibly with type ptrdiff_t) that give the number of bytes from a base location to the key and the message. The beginning of the shared memory segment is a typical base to use.
If you have only one key and one message to shared, then a common way this is done is simply to use a single data structure for the shared memory, as you showed with your second definition of shared_data: The key and the message are part of the struct, so their offsets are known, simply as offsets from the beginning of the struct. If you are sharing more complicated data, such as trees or linked lists, then you may need to use explicit offsets.
I know how to work with pointers. But I don't know how do this:
I have an hex address that's of course it has a any value from any app.
I know to find the address that I want.
I want to write a C Code to pass this address to a pointer variable, and then I could capture the value from that address and so on.
For example:
hex 0x00010010
int *pointer;
How can I pass this address to the pointer, what's the syntax for that?
By using int* you are assuming the data you are point to is an int (4 bytes, on most OS's).
Shouldn't we use a void* instead? Later, if you want to access it's data using a particular type, all you need to do is cast.
void *addr = (void*)0x0023FF74; // valid memory address within my app
printf("Address: %p\n", addr);
getchar();
printf("Data (4bytes): %d\n", *(int*)addr); // print the first 4 bytes of data as int
getchar();
EDIT:
Help me understand what you are trying to do, because this statement confused me:
There is app using that address, I know the value in it, but the (int)pointer don't access the value.
Are you trying to write an application that will modify the memory of another application that is running your system? Your current approach won't work, and this is why: When the Operating System loads your application into a process, it reserves a memory region to be used by the process and assigns a range of virtual addresses to this region. These virtual addresses do not map directly to memory addresses in RAM, so the OS has to keep an internal table for that.
On Windows, each process loaded receives the same range of virtual addresses, but this area is only visible to the process that is running inside it. For instance, (on Windows) processes are loaded in memory address 0x00400000, which mean each process has it's own memory address 0x00400000, and therefore you can't assign X memory address to a pointer in your application and expect Windows to magically know that you are reffering to address X that is inside another application.
What you are trying to accomplish it's called Code Injection, and there's a lot of information on the web about it.
In typical modern operating systems, you cannot access another process' (app's) address space. The addresses are virtual, so the same numerical value means different things to different processes.
If you are on a system with a true "flat" address space (where processes directly work with actual physical memory addresses) such as Amiga OS on the 680x0, you can do something like:
int *pointer = (int *) 0x00010010;