Answers to questions in your head: Yes, this is for school. No, I can't use threads for this. And yes, I looked for an answer and some people said "yes" and others said "no." I'm also fact-checking my professor because I don't want to unfairly lose points if someone else were to grade it and they require this to be "fixed."
With that being said... consider this simple program for c on the Linux system. I malloc something and then fork. I boiled down my project to the exact problem:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
int main( void )
{
char * args [] = { "someinvalidcommand", NULL };
// malloc before the fork (happens in parent process)
char * something = (char *)malloc(sizeof(char));
pid_t child_pid = fork();
// are there now two things that need to be freed:
// one for each process?
if(child_pid == 0) // child process
{
//free(something); // is this needed?
// execvp (it won't return if succeeded)
if(execvp(args[0], args) < 0)
{
// or do I only need to free it here?
printf("%s: No such file or directory\n", args[0]);
/*
* EDIT: Calling it here seems to fix the issue. It turns out
* that the system calls were the ones with the "still reachable"
* errors, so I guess it's not all that important that the
* memory be freed.
*
* free(something)
*/
_exit(1);
}
}
else // parent process
{
int status;
while(wait(&status) != child_pid);
if(status != 0)
{
printf("command status: %i\n", WEXITSTATUS(status));
}
}
free(something);
return 0;
}
Now this is where it's slightly confusing. To my knowledge, fork creates an exact copy of the parent process at that particular state (including text, data, etc.). I read somewhere that this includes anything malloc'd (so, the heap). However, I read somewhere else that it doesn't because of something called "copy-on-write," but then I read somewhere else that "copy-on-write" is simply an optimization that's transparent and irrelevant. But then what I read that made the most sense was that since it's a COPY, it has its own, well... everything.
But then I recall that when fork() is used, whatever was malloc'd will contain the same memory address, so are the parent and child pointing to the same thing? Do I need to free resources in the child, as well? Are only the pointers copied, or are the data that the pointers are pointing to also copied?
I used valgrind and when the child process exits, it simply complains that all the memory is still reachable. How exactly is it "still reachable?" Does the fact that it's "still reachable" answer my question and say that the parent and child are pointing to the same thing and the parent's the only one responsible for freeing the memory?