Должны ли мы использовать выход или возврат в дочернем процессе - PullRequest
7 голосов
/ 11 мая 2019

Сказать, что я использовал fork для создания одного дочернего процесса. Вот пример:

pid_t pid=fork();
if (pid==0) /* child */
{
    // do something
    exit(0); // _exit, exit or return????
}
else /* parrent */
{
    wait(nullptr);
    return 0;
}

Я видел много примеров fork. Некоторые из них использовали _exit для завершения дочернего процесса, чтобы избежать очистки буфера ввода / вывода, другие использовали exit для завершения дочернего процесса. Но ни один из них не использовал return. Насколько я понимаю, _exit и exit не будут вызывать деструкторы автоматически, поэтому лучше ли вызывать return вместо exit в дочернем процессе? Или потому что все примеры, которые я когда-либо видел, это C, а не C ++, поэтому им не нужно беспокоиться о деструкторах?

Ответы [ 4 ]

0 голосов
/ 12 мая 2019

Выход команды следует избегать использовать в любом случае, кроме как от прекращения выполнения программы. Для всего остального я бы использовал return.

0 голосов
/ 11 мая 2019

fork скопирует весь процесс, что не эквивалентно запуску потока с новой основной функцией. Возвращение просто вернется из текущей функции, и выполнение дочернего элемента продолжится в функции включения.

Так что в своем фрагменте вы должны убить ребенка, иначе он "сбежит". Вы можете сделать это, позвонив по номеру exit() или std::terminate(). В обоих случаях деструкторы не вызываются. Не смешивайте два разных языка.

Если вам действительно нужно вызывать деструкторы у ребенка, бросьте исключение и перехватите его в main. Это правильно размотает стек.

0 голосов
/ 11 мая 2019

Вы можете использовать _exit или exit, но не следует использовать return.Когда вы разветвляете дочерний элемент, вы сохраняете весь стек вызовов как часть разветвления дочернего элемента.Поэтому, если вы используете return, вы в конечном итоге вернетесь к своей программе, продолжая выполнять другие задачи, что почти наверняка не то, что вам нужно.

Например, если у вас есть что-токак этот фрагмент:

int get_value()
{
    pid_t pid;
    if (!(pid = fork())) {
        int x = 0;
        // do something with x.
        exit(x);
    }
    else {
        int status;
        wait(&status);
        return status;
    }
}

int main()
{
    int value = get_value();
    switch (get_value()) {
        case 0:
            // call f
            break;
        case 255 << 8:
            // call g
            break;
    }
}

вы можете в конечном итоге вызвать f или g или выполнить другую работу с return, что определенно нежелательно.

Если вы вызываете _exit, функции, зарегистрированные с помощью atexit, не вызываются.Это правильная вещь в многопоточных средах.Если вы не работаете в многопоточной среде и у вас нет обработчиков, зарегистрированных с помощью atexit, то они должны быть функционально эквивалентны.

Если вы хотите, чтобы деструкторы в вашем дочернем процессе вызывались, поместитекод дочернего процесса в его собственной функции и позволяет его переменным автоматически уничтожаться, когда они выходят из области видимости.exit не будет уничтожать объекты для вас, что хорошо, потому что обычно вы не хотите уничтожать объекты, созданные в родительском процессе в вашем дочернем процессе.

0 голосов
/ 11 мая 2019

Вы можете использовать return, если вы ищете код выхода дочернего процесса, просто чтобы сказать, что процесс запущен и выполнен правильно / нет.То же, что вы делаете со своей основной функцией в программе.В противном случае просто используйте выход, чтобы остановить процесс дальше.

...