Я создал простую программу-оболочку, которая
_отображает подсказку
_получает пользовательский ввод с помощью readline()
_разбивает ввод на слова в зависимости от того, где во входной строке встречаются пробелы
_ затем слова помещаются в массив (который обрабатывается MALLOC);
_fork() используется для создания дочернего процесса
_i затем передайте этот массив для вызова программы из дочернего процесса с помощью execve()execve(myarray[0], myarray, env);
и текущий процесс ждет его.
МОЙ ВОПРОС:
Нужно ли мне освобождать MALLOC-память myarray
?
Вот часть кода
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 }
Если execve() успешно, может ли это вызвать утечку памяти из-за массива malloc?
Проведите эксперимент.
Если это один процесс (он не вызывает fork()
), это не приведет к утечке памяти. Но вы упомянули, что текущий процесс ждет этого, поэтому я сомневаюсь. Пожалуйста, покажите полный код, где массив обрабатывается, вызывается execve() и что "ждет этого".
В настоящее время я тестирую свой код с помощью valgrind, и я продолжаю получать утечки памяти, но не могу понять, откуда они. Следовательно, вопрос @AllanWind
Отвечает ли это на ваш вопрос? Что происходит с распределенной памятью после того, как exec() изменит образ программы?
Да, вам нужно освободить память в родительском процессе. Вопрос, который я связал, содержит более подробную информацию.
@AllanWind, этот вопрос больше касается поведения fork
, которое не используется в этом вопросе. (ну, во всяком случае, не так, как было описано)
@MM Это говорит о exec. Может я что-то упускаю?
OP, пожалуйста, уточните вопрос - execve
заменяет вызывающий процесс новым процессом, «родительского процесса» нет. Если вы используете fork
, укажите это в вопросе
@M.M Я предположил, что родитель «и текущий процесс ждет его».
Форк использовался для создания дочернего процесса. Затем в родительском процессе используется wait()
@NwaburuEmekaChristian Массив выделяется в родительском процессе до fork () или в дочернем процессе после?
@dimich Выделяется после fork() в дочернем процессе
Я включил часть кода
@NwaburuEmekaChristian Вы можете оставить free_array(splitted_str)
, оно будет выполнено, если execve()
потерпит неудачу. Конечно, если вы не используете его позже в дочернем процессе. И результат проверки execve()
избыточен: он либо возвращает -1, либо не возвращает.
Нужно ли мне освобождать MALLOC-память myarray?
Вам не нужно освобождать его в процессе, который вызывает execve()
. В случае успеха эта функция заменяет весь образ процесса новым, так что нечего освобождать и нет способа его освободить. Для целей новой программы второй аргумент main()
и строки в этом массиве не выделяются динамически и не могут быть освобождены. С другой стороны, при сбое execve()
вызывающий процесс должен немедленно завершиться, и этого достаточно для удовлетворения любой потребности в освобождении выделенной памяти в этом процессе.
Однако, если вы выполняете выделение до fork
ing, что, похоже, вы и делаете, то вам, вероятно, нужно освободить память в процессе, который не вызывает execve()
. Вы можете не беспокоиться, если этот процесс все равно скоро завершится, но если он будет продолжать работать бесконечно, обрабатывая неопределенное количество дополнительных команд, вам следует освободить память, когда вы закончите с ним.
Почему вы должны немедленно прекратить работу в случае execve()
неудачи? Я никогда не слышал этого раньше.
@root: какая альтернатива? Ребенок был создан для выполнения определенной программы. Если он не может его выполнить, какое дерьмо делать вместо этого? Найти исходный код, скомпилировать и выполнить его? Применить машинное обучение, чтобы решить, как записать недостающий исходный код?
@root, я удивлен, что ты никогда этого не слышал. Это совершенно обычно и вполне разумно. Альтернативой является продолжение дочерним процессом кода родительского процесса, что редко, если вообще когда-либо, имеет смысл. Более того, если родитель wait()
за дочернего, то он будет продолжать делать это до тех пор, пока дочерний не завершится, даже если дочерний делает что-то отличное от того, для чего он был разветвлен.
Я думал, вы имеете в виду какую-то техническую причину (например, не гарантируется, что образ памяти останется неповрежденным). Я помню, как видел оболочку, которая при запуске myprogram
проходила каждый путь в PATH
и пробовала execve("path/myprogram", ...)
, пока не добилась успеха.
execve()
заменить текущий образ процесса, так куда звонитьfree()
? После успешногоexecve()
ваш код больше не выполняется. Или вы хотите освободить его в родительском процессе послеfork()
?