Not that long ago, I had an idea for some simple inter-process comunication: one process outputs an address to a pointer, I copy that to the input of another process, and that changes the original variable.
I implemented it like this:
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
bool p;
cin>>p;
if(p){
int n;
n=0;
cout<<&n;
cin.get();
cin.get();
cout<<n;
}else{
int *point,n;
scanf("%p",&point);
cout<<point;
cin>>n;
*point+=n;
}
return 0;
}
I used scanf because cin complained, and wouldn't compile. I tried to run it, with two processes, but after I launched the second instance, and input the pointer's address, as outputed by the first, it froze. As I only have access to Windows, I have no idea as to whether it got a SIGSEGV, or if it did something completely diferent.
Is it just me trying to change the value of another process's variable that is crashing it, or is it something else that is stopping me?
You cannot do this that way because first process will not have access to the second process' memory address space (in common operating systems, including Windows and Linux).
Each process has its own memory, completely separate from that of other processes. A pointer value is meaningless in context of a different process, even if you manage to get it across.
Related
Just a miscellaneous question.
I have a program in C++:
#include <stdio.h>
int main()
{
while (1) {
int value1 = 1;
printf("%p\n", (void *)&value1);
void* address = (void *)&value1;
int value2 = *(int*)address;
printf("%d\n",value2);
}
return 0;
}
What this does is get the address of value1, store it in address, and then get the variable in address and store it in value2.
This works just fine, however, I would like to access the variable from another C++ program. I have tried this (two methods in this one file):
#include<iostream>
#include <cstdint>
int main() {
std::cout << "before seg fault" << std::flush;
uintptr_t p = <address>;
int value = *reinterpret_cast<int *>(p);
int value2 = *(int*)<address>;
std::cout << "after seg fault"<< std::flush;
std::cout << value;
return 0;
}
This causes a segmentation fault when trying to access the value, which is probably because the OS doesn't want me accessing this value or because it doesn't exist in this instance.
However unpractical and stupid this may seem, is there a way to overcome this? Or is it impossible? As a side note, Why should / why shouldn't I do this?
Edit: I have approved Chris's answer, as it works just fine when you run it with root on linux. Would it be too much to ask for something that works on Mac and Windows too? I have tried running the poke program on Mac system and it gives error: Can't access pid 26112:: No such file or directory, invoked by line:
fprintf(stderr, "usage: %s pid address value\n", av[0]);
Each process has it's own address space and addresses in a program refer to that address space, independent of the addresses in any other address space. So when you put an explicit value into a pointer like that and use it, you'll get whatever is at that address in this process (which is probably invalid, so you get a SEGFAULT or similar error), rather than accessing the other process.
On most OSes, there are ways to access the address space of another process, subject to permissions. For example, on Linux, this poke program can modify another process's address space:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int main(int ac, char **av) {
char name[64];
int fd;
if (ac != 4) {
fprintf(stderr, "usage: %s pid address value\n", av[0]);
exit(1); }
sprintf(name, "/proc/%.10s/mem", av[1]);
if ((fd = open(name, O_WRONLY)) < 0) {
fprintf(stderr, "Can't access pid %s", av[1]);
perror(":");
exit(1); }
lseek(fd, strtol(av[2], 0, 0), SEEK_SET);
if (write(fd, av[3], strlen(av[3]) + 1) < 0)
perror("write");
return 0;
}
If you then run this program:
#include <stdio.h>
#include <unistd.h>
int main() {
char data[16] = "test";
while (1) {
printf("pid = %d, &data = %p, data = %s\n", getpid(), &data, data);
sleep(2);
}
}
It will print lines looking something like:
pid = 6376, &data = 0x7ffe255f3190, data = test
pid = 6376, &data = 0x7ffe255f3190, data = test
and if you run ./poke 6376 0x7ffe255f3190 Hello in another window/terminal, it will change to
pid = 6376, &data = 0x7ffe255f3190, data = Hello
pid = 6376, &data = 0x7ffe255f3190, data = Hello
This causes a segmentation fault when trying to access the value, which is probably because the OS doesn't want me accessing this value or because it doesn't exist in this instance.
The latter. The virtual memory address of one process doesn't have a meaning to the other process. Unless the process attempting to read the arbitrary address incidentally had allocated memory in the same virtual address, the operating system notices that it's doing non-sensical things, and terminates it in order to prevent the process from doing non-sensical things that may have bad consequences.
Can you access another program's stack/heap if you know the address?
There is no standard way to do that in C++. The language lacks the concept of multiple processes.
A co-operative way for processes to communicate is to use shared memory. There is no standard way to allocate shared memory in C++.
Reading memory of another process without co-operation may also be possible, although operating systems typically prevent regular users from doing that by default for obvious reasons - unless the processes belong to the same group. There's no standard way to do this in C++ either.
Why should / why shouldn't I do this?
The co-operating shared memory is useful for inter-process communication. Note that there are other alternatives too, such as pipes and sockets (but none of the alternatives are in standard C++).
The non-co-operative reading of another process is rarely useful in user space programs. I suppose that debuggers doing this is one of such rare use cases.
This causes a segmentation fault when trying to access the value, which is probably because the OS doesn't want me accessing this value or because it doesn't exist in this instance.
Sort of both: it doesn't exist in your process's address space because the OS doesn't want you accessing other processes' memory, and therefore instructed the memory hardware not to map it into your process's address space.
In some old, single-user operating systems, you could access all memory, because there was no real concept of process isolation, or users, or the virtual memory hardware to enforce any separation.
The reason this isn't done any more is because it scales really badly. Once you have a few background tasks, things start to break if they don't get scheduled regularly (or if they take too long about yielding the processor). Once you have a few processes, things start to break if they accidentally trample each other's memory.
So now we have self-contained processes which can only communicate by mutual agreement (such as by both mapping some shared memory), but cannot trample over each other's variables.
However unpractical and stupid this may seem, is there a way to overcome this? Or is it impossible? As a side note, Why should / why shouldn't I do this?
You shouldn't do this (that is, exactly what you're asking) for the same reason the OS is preventing you: it causes impossible-to-diagnose bugs and security leaks in random parts of your system.
If you want to share memory between processes, you can use shared memory. It's very platform-specific, so you need to look up the API for a specific platform, or use Boost.Interprocess.
Note however that the same memory may be mapped at different addresses in each process using it, so you can't usefully store pointers inside it (but offsets are OK), and it's a lot of work to implement things like node-based containers in shared memory (but Boost.Interprocess has ones you can use).
I am just trying to get Value stored at a specific memory address using two C++ codes
Code which I using to write data to memory and get its address :
#include <iostream>
using namespace std;
int main()
{
int i = 10;
cout<<&i<<endl;
cin>>i; // This is just to make sure program doesn`t end
return 0;
}
I used cin>>i; just to make sure that it doesn't end.
After getting the address of int i, put in the following code :
#include <iostream>
using namespace std;
int main()
{
// This address changes everytime and I change it everytime
// This is just one temporary address
volatile int *x = (volatile int *)0x7ffef9246e74; // [1]
int y = *x;
cout<<y<<endl;
return 0;
}
[1] : I copied this line from this page.
Program #1 keeps running while I run Program #2
On running the second code, I am getting segmentation fault (core dumped). Any help?
Your model of how modern operating systems, compilers, etc. work is wrong. When you run the program the first time, the process gets assigned a memory space. Everything within this memory space, which is a virtual memory space, gets mapped to physical memory by the processor's MMU.
When the process finished, its memory space no longer exists. The next time you start the same program, it will run in another and independent memory space. It might be mapped to different physical memory addresses and even the virtual addresses are either not the same or they are cleared to make sure that no information is leaked from former processes.
This means that when you enter the address from the first program into the second, it has no meaning there. What is worse is that the memory address from the first run is not part of the virtual memory space of the second one when you run it, hence the CPU's MMU detects an illegal access to a memory location and you get a seg-fault.
I didn't found this question in Stack Overflow or Google, so sorry if it's a duplicate.
As I know, variables in C/C++ are not initialized. But recently a strange situation occur to me when using pointers. See the code below:
#include <iostream>
using namespace std;
struct Test {
int i;
};
struct Box{
Test *var;
};
int main() {
Box *t = new Box;
cout << t->var;
}
In Windows, the output I get is something like (what is expected):
0x3e0178
But, in Unix systems, the output is:
0x0
Why this happen? Does the compiler initialize the pointers in a recursive way when new is invoked in Unix systems?
Also, with common variables the same happens. For the code below, the results are 0 in Unix systems and 4385838 in Windows:
int main() {
int i;
cout << i << endl;
}
UPDATE
In another test, the behavior this time was the same in both systems: the pointer p points to a random address in the memory.
int main() {
int *p;
cout << p;
}
Just to explain my question: I know we have to initialize the variables before using it, but a student was asking me why his program works fine in Unix systems and not in Windows. I found this pointer issue in his program, and I want to give a feedback.
In all modern (multiuser) operating systems, memory received directly form the os is zeroed, in order to avoid information leakage. What happens, is probably the Unix systems, because far less startup code must be run to set up a proper C runtime environment, main() by dumb luck got virgin memory, not reusing stack space previously used for a different function, to store i. The other possible explanation is, someone just stored a 0 there before.
Anyway, don't rely on it for heavens sake.
This code is C/C++ and runs without warnings or debug messages. I'm using Code::blocks with the GNU GCC compiler. This app worked perfectly once, then somewhere along the lines I messed up without noticing. Now every time it will allow a ip address input, but then freeze up and close. Why?
#include <iostream>
#include <string>
#include <cstdio>
using namespace std;
int ip[3];
char * inputIP;
int x;
string classValue;
void subnetClass()
{
if (x==0) classValue="Error: first octet may not be zero.";
if (x>0 && x<=126) classValue="Class A";
if (x==127) classValue="Loopback Address";
if (x>=128 && x<=191) classValue="Class B";
if (x>=192 && x<=223) classValue="Class C";
if (x>=224 && x<=239) classValue="Class D";
if (x>=240 && x<=255) classValue="Class E";
if (x>255) classValue="Error: an octet may not be more than 255.";
cout << classValue << endl;
}
int main()
{
cout << "Enter IP address in dotted-decimal form." << endl;
cin >> inputIP;
scanf(inputIP, "%d.%d.%d.%d" , &ip[0],&ip[1],&ip[2],&ip[3]);
int x=ip[0];
subnetClass();
return 0;
}
Build Log:
Checking for existence: C:...\IP subnetting app\bin\Debug\IP subnetting app.exe
Executing: "C:...\CodeBlocks/cb_console_runner.exe" "C:...\IP subnetting app\bin\Debug\IP subnetting app.exe" (in C:...\IP subnetting app.)
Process terminated with status -1073741510 (0 minutes, 27 seconds)
You are declaring a variable 'x' that is hiding the global one.
int x=ip[0];
However, don't do it this way. Add an int parameter to subnetClass and pass in the value that way, and remove the global variable.
Really, removing all of your globals should be a goal and easy to accomplish. Several are only used in main().
It might have worked with a little help from sheer luck even if you messed things up later, I believe. More or less everything is wrong. First you read the line into the area pointed to by uninitialized pointer (or maybe you read the pointer value, I'm not even sure what >> (char*) is supposed to do). You better change the definition to
std::string inputIP;
then you try to parse it used scanf and pass this pointer as a format string. What you meant is using sscanf. Assuming you changed the inputIP type, you can use
sscanf(inputIP.c_str(),"%d....
Then you assign to local main variable x that shadows global, which remains uninitialized when you use it in the function. Just remove the int part in the assignment like this:
x=ip[0];
and make the ip array of four elements.
int ip[4];
Then it may work. Unless I missed something else.
And one more thing: if you use some source control (for instance using git you may start new project in no time) then you'd know what you've changed when you mess up, just commit early, commit often.
Use sscanf instead of scanf
Recently I've time off of school for a few days and wanted to do a small program(s) experiment in C++ dealing with memory address.
I wanted to see is that if a currently running program (Let call it Program A) that created a pointer to an int object in the heap, can be seen by another program and be modified (Program B).
So for Program A, this is my basic code:
// Program A
#include <iostream>
using namespace std;
int main()
{
// Pointer to an int object in the heap
int *pint = new int(15);
// Display the address of the memory in heap
cout << pint << endl;
// Display the value stored in that address
cout << *pint << endl;
return 0;
}
Output for Program A:
0x641030
15
For Program B, I looked at how to assigned a specific memory address through this link:
http://www.devx.com/tips/Tip/14104
The code for Program B is:
// Program B
#include <iostream>
using namespace std;
int main()
{
// assign address 0x641030 to p
int *p = reinterpret_cast< int* > (0x641030);
cout << p << endl;
cout << *p << endl;
return 0;
}
Output for Program B:
0x641030
... "Crash"
I don't quite understand it. I was expecting a display of 15 from *p, but it did something i didn't expect.
I also tried to assign *p to a number like *p = 2000 but it crashed when I attempted that as well.
Also when I display the address of the pointers and Program A (cout << &pint;) and for Program B (cout << &p;), they both showed the same memory address.
Does anyone know what is going on exactly? I'm interested yet confused of what is happening. Also, is it possible for me to do what I am attempt in C++/C ?
** EDIT **
Sorry to not mention my platform, but I am currently using Window 7 Professional
The short answer is that different processes use completely different address spaces. Without doing a lot more work, process B can't read or write the memory from process A.
It is possible to do this, in a platform-specific way. Win32 offers functions such as WriteProcessMemory where you can directly poke values into the memory space of another process. Most operating systems offer a shared memory function, with Win32 you can use memory mapped files and Unix flavours typically have some kind of equivalent "mmap" or "shmem" feature.
I think that most operating systems are designed to make it impossible (or very difficult) to do what you are trying to do -- have one running program (or process) interfere with the contents of the address space of another running program (or process). Since you don't tell us your platform it's difficult to be categorical about this, but I suspect that the o/s is saving you from yourself. This rigid separation of processes is a safety feature on single-user machines, a safety and security feature on multi-user machines.
There are, of course, many techniques for running concurrent processes which can share memory or which exchange information by message-passing. Take some more time off school and study those!
Take a look at either Memory Mapped Files or Shared Memory.
http://msdn.microsoft.com/en-us/library/aa366551(VS.85).aspx