0

I created a simple shell program that
_displays a prompt
_receives user input using readline()
_splits the input into words based on where spaces are found in the input string
_the words are then put in an array (which is MALLOC'ed);
_fork() is used to create a child process
_i then pass this array to call a program from the child process using execve()
execve(myarray[0], myarray, env); and the current process waits for it.

MY QUESTION IS: Do i need to free the MALLOC'ed memory of myarray ?
Here is a part of the code

  child_pid = fork();
 42                 if (child_pid == -1)
 43                 {
 44                         perror(argv[0]);
 45                         free(linebuffer);
 46                         return (2);
 47                 }
 48
 49                 if (child_pid == 0)
 50                 {
 51                         /*strsplit() returns MALLOC'd array*/
 52                         splitted_str = _strsplit(linebuffer, ' ');
 53
 54                         if (execve(splitted_str[0], splitted_str, env) == -1)
 55                         {
 56                                 perror(argv[0]);
 57                                 
             /*Function that frees a NULL terminated array*/  
free_array(splitted_str);
 58                                 free(linebuffer);
 59
 60                                 return (2);
 61                         }
 62                 }
 63                 else
 64                 {
 65                         wait(NULL);
 66                 }
  • 1
    `execve()` replaces current process image, so where to call `free()`? After successfull `execve()` your code is not executing anymore. Or do you mean to free it in parent process after `fork()`? – dimich Nov 16 '22 at 03:37
  • If execve(), is successful, can it cause memory leaks due to the malloc'd array? – Nwaburu Emeka Christian Nov 16 '22 at 03:41
  • Run the experiment. – Allan Wind Nov 16 '22 at 03:47
  • 1
    If it is a single process (it doesn't call `fork()`) it will not cause memory leak. But you mentioned *the current process waits for it*, so i doubt. Please show full code, where the array is malloced, execve() is invoked and what is "waits for it". – dimich Nov 16 '22 at 03:48
  • I am currently testing my code using valgrind and i keep getting memory leaks but can't figure out where they are from. Hence, the question @AllanWind – Nwaburu Emeka Christian Nov 16 '22 at 03:49
  • 1
    Does this answer your question? [What happens to malloc'ed memory after exec() changes the program image?](https://stackoverflow.com/questions/5429141/what-happens-to-malloced-memory-after-exec-changes-the-program-image) – Allan Wind Nov 16 '22 at 03:49
  • Yes, you need to free the memory in the parent process. The question that I linked provides more detail. – Allan Wind Nov 16 '22 at 03:51
  • @AllanWind that question is more about the behaviour of `fork` which is not being used in this question. (well, not as has been described anyway) – M.M Nov 16 '22 at 03:53
  • @M.M It talks about exec. Maybe I missing something? – Allan Wind Nov 16 '22 at 03:54
  • 2
    OP please clarify the question -- `execve` replaces the calling process with a new process, there is no "parent process". If you are using `fork` please include that in the question – M.M Nov 16 '22 at 03:55
  • @M.M I assumed parent with "and the current process waits for it." – Allan Wind Nov 16 '22 at 03:56
  • Fork was used to create the child process. Then wait() is used in parent process – Nwaburu Emeka Christian Nov 16 '22 at 04:03
  • @NwaburuEmekaChristian The array is allocated in parent process before fork() or in child process after? – dimich Nov 16 '22 at 04:07
  • @dimich It is allocated after fork() in the child process – Nwaburu Emeka Christian Nov 16 '22 at 04:11
  • I have inluded a part of the code – Nwaburu Emeka Christian Nov 16 '22 at 04:21
  • @NwaburuEmekaChristian You can leave `free_array(splitted_str)`, it will be executed if `execve()` fail. Of course, if you don't use it later in child process. And checking result of `execve()` is redundant: it either return -1 or doesn't return. – dimich Nov 16 '22 at 05:12

1 Answers1

2

Do i need to free the MALLOC'ed memory of myarray ?

You do not need to free it in the process that calls execve(). On success, that function replaces the entire process image with a new one, so there is nothing left to free and no way to free it. For the purposes of the new program, the the second argument to main() and the strings in that array are not dynamically allocated and cannot be freed. On execve() failure, on the other hand, the calling process ought to terminate immediately, and doing so is sufficient to serve any need to free allocated memory in that process.

However, if you perform the allocation before forking, which it sounds like you do, then you probably do need to free the memory in the process that does not call execve(). You might not bother if that one were going to terminate soon anyway, but if it's going to continue running indefinitely, processing an indefinite number of additional commands, then you should free the memory when you are done with it.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Why ought you terminate immediately on `execve()` failure? I've never heard that before. – root Nov 16 '22 at 08:43
  • 1
    @root: what is the alternative? The child was created to execute a specific program. If it can't execute it, what shit do instead? Go find the source and compile and execute that? Apply machine learning to decide how to write the missing source? – Jonathan Leffler Nov 16 '22 at 10:16
  • @root, I'm surprised that you haven't ever heard that. It is absolutely usual and wholly sensible. The alternative is for the child to continue running the code of the parent process, which rarely, if ever, makes sense. What's more, if the parent `wait()`s for the child then it will continue to do so until the child does terminate, even though the child is doing something different from what it was forked to do. – John Bollinger Nov 16 '22 at 14:45
  • I thought you were referring to some technical reason (e.g. the memory image is not guaranteed to remain intact). I remember seeing a shell that, when launching `myprogram` traversed each path in `PATH` and tried `execve("path/myprogram", ...)` until it succeeded. – root Nov 16 '22 at 18:22