I have created a parent and a child process using fork( ), and both share a memory address called “ptr”. But i am confused due to the one output of a program:
1) Address of ptr: 123456
NOTE: Same address for both parent and child, so expected is if one process alters this address, it should reflect for the other too process too as the address is same.
2) Parent: *ptr=44
3) Child: *ptr=33
4) Printing values:
Parent still retains old value: printf(“ptr = %d”,*ptr); // Output: still 44, exp is 33
Child prints 33, the expected value. printf(“ptr = %d”,*ptr);//Prints 33 fine
Question1) Can anyone tell me, how the values are different? Although the pointer address is same for both the parent and the child?
Question2) I am working on a memory leak tool which is giving double free, error as it is seeing parent and the child free the same address. However, it is not a case of double free, as we see. How to sort this problem? As the memory address the tool sees for the parent and the child is the same addrerss?
P.S: Please see the below code snippet:
#include <sys/types.h>
#include <unistd.h>
#include <cstdlib>
int main()
{
int pid, *ptr
ptr=(int*)malloc(sizeof(int));
*ptr=33; // Parent keeps the data as 33, before forking.
if(pid==0){*ptr=44;} // Child modifies data, which is ignored by parent
// Now we print the memory address and the value both by child and parent
if(pid==0)
{
printf("Child data: %u\n",*ptr);
printf("Child address: %u\n",ptr);
}
if(pid>0)
{
printf("Parent data: %u\n",*ptr);
printf("Parent address: %u\n",ptr);
}
}
Output:
Child data: 44
Child address: 123456
Parent data: 33 (how come still old value?)
Parent address: 123456 (How come same address but data different than child?)
This is the whole idea. They may have the same address, but these addresses are virtual. Each process has its own address space. What
fork()does is creates a new process, and makes its virtual memory layout look like the parent.See the Wikipedia article on page tables and similar topics for some illustrations of how this works.
— (Long aside follows) —
What typically happens at a
fork()is that page tables for both the parent and child are set up such that the pages are marked as read-only. When a write instruction happens for some location the kernel gets a page fault, which the CPU generates at a bad memory access. The kernel will allocate new memory for the trapped process, map it into the right address by manipulating its page table, copy the old buffer to the newly allocated one and let the write continue. This is called copy-on-write. This makes the initial fork quick and keeps memory consumption down for pages that are not written in either process.The previous paragraph is all just an optimization of the fork programming model. They say early Unix didn’t do this — it did a full memory copy of the whole process. I’ve also heard that Cygwin’s
fork()does a full copy.But the virtual address has nothing to do with the physical address of the memory. The CPU uses it as a “key” for the page table, which defines where the actual memory is. The page table may also say that the page is not valid, in which case the kernel has an opportunity to do a “fixup” (perform copy-on-write, recall the page from swap space, etc.) or kill the process in the case of a legitimately invalid pointer access.