Подтвердить что ты не робот

Возможно ли перезапустить программу изнутри программы?

Я разрабатываю С++-программу, и было бы полезно использовать некоторую функцию, script или что-то, что заставляет программу перезапускаться. Это большая программа, поэтому перезагрузка всех переменных вручную займет у меня много времени...

Я не знаю, есть ли способ достичь этого или если это возможно.

4b9b3361

Ответ 1

Если вам действительно нужно перезапустить всю программу (т.е. "закрыть" и "открыть" снова), "правильным" способом будет иметь отдельную программу с единственной целью перезапустить основную. AFAIK много приложений с функцией автоматического обновления работают таким образом. Поэтому, когда вам нужно перезапустить основную программу, вы просто вызываете "регенератор" один и выходите.

Ответ 2

Вы можете использовать цикл в вашей функции main:

int main()
{
    while(!i_want_to_exit_now) {
        // code
    }
}

Или, если вы хотите перезапустить программу, запустите ее из жгута проводов:

program "[email protected]"
while [ $? -e 42 ]; do
    program "[email protected]"
done

где 42 - код возврата, означающий "перезагрузите, пожалуйста".

Затем внутри программы ваша функция restart будет выглядеть так:

void restart() {
    std::exit(42);
}

Ответ 3

В Unicies или где-либо еще у вас есть execve и он работает как справочная страница, вы можете просто... убить меня за использование atoi, потому что это вообще ужасно, за исключением такого рода случаев.

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main (int argc, char** argv) {

  (void) argc;

  printf("arg: %s\n", argv[1]);
  int count = atoi(argv[1]);

  if ( getchar() == 'y' ) {

    ++count;

    char buf[20];
    sprintf(buf, "%d", count);

    char* newargv[3];
    newargv[0] = argv[0];
    newargv[1] = buf;
    newargv[2] = NULL;

    execve(argv[0], newargv, NULL);
  }

  return count;
}

Пример:

$ ./res 1
arg: 1
y
arg: 2
y
arg: 3
y
arg: 4
y
arg: 5
y
arg: 6
y
arg: 7
n

7 | $

(7 - код возврата).

Он не повторяется и не конкретизирует циклы - вместо этого он просто вызывает себя, заменяя собственное пространство памяти новой версией самого себя.

Таким образом, стек никогда не будет переполняться, хотя все предыдущие переменные будут обновлены, как и при любой перегруппировке - вызов getchar предотвращает 100% использование ЦП.

В случае самообновляющегося двоичного файла, поскольку весь двоичный файл (по крайней мере, в Unix-подобных, я не знаю о Windows) будет скопирован в память во время выполнения, а затем, если файл изменится на диск до вызов execve(argv[0], ..., вместо этого будет запущен новый двоичный файл, найденный на диске, а не тот же старый.

Как отмечают @CarstenS и @bishop в комментариях, из-за уникального способа разработки Unix открытые дескрипторы файлов хранятся в fork/exec, и в результате во избежание утечки файловые дескрипторы во всех вызовах execve, вы должны либо закрыть их до execve, либо открыть их с помощью e, FD_CLOEXEC/O_CLOEXEC в первую очередь - более подробную информацию можно найти на блог Дэна Уолша.

Ответ 4

Это очень специфичный для ОС вопрос. В Windows вы можете использовать API перезагрузки приложений или MFC Restart Manager. В Linux вы можете сделать exec()

Однако большую часть времени существует лучшее решение. Вероятно, вам лучше использовать цикл, как это предлагается в других ответах.

Ответ 5

Это похоже на неправильный подход, так как все ваше состояние является глобальным, и поэтому единственный способ очистки, который вы имеете для сброса всего (кроме того, чтобы вручную назначать значения по умолчанию для каждой переменной) - это перезапуск всей программы.

Вместо этого ваше состояние должно храниться в объектах (типа класса или любого другого). Затем вы можете создавать и уничтожать эти объекты, когда захотите. Каждый новый объект имеет новое состояние со значениями по умолчанию.

Не сражайтесь с С++; используйте его!

Ответ 6

Вероятно, вам нужен цикл:

int main()
{
    while (true)
    {
        //.... Program....
    }
}

Каждый раз, когда вам нужно перезапустить, вызовите continue; в цикле и для завершения вашей программы используйте break;.

Ответ 7

Когда я разрабатываю системы реального времени, мой подход обычно является "производным основным()", где я пишу весь код, вызванный из реального main(), например:

Программа main.cpp:

int main (int argc, char *argv[])
{
   while (true)
   {
       if (programMain(argc, argv) == 1)
           break;
   }
}

Программа program.cpp, где записывается весь код:

int programMain(int argc, char *argv[])
{
    // Do whatever - the main logic goes here

    // When you need to restart the program, call
    return 0;

    // When you need to exit the program, call
    return 1;
}

Таким образом, каждый раз, когда мы решаем выйти из программы, программа будет перезапущена.

Подробно: все переменные, глобальные переменные и логика должны быть записаны внутри programMain() - ничего внутри "main()", кроме элемента управления перезапуска.

Этот подход работает как в Linux, так и в Windows.

Ответ 8

Мне кажется, что вы задаете неправильный вопрос, потому что вы недостаточно знаете о кодировании, чтобы задать правильный вопрос.

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

В качестве побочного примечания, если ваша программа занимает 5 секунд для инициализации всех ваших переменных, она все равно займет 5 секунд при ее перезапуске. Вы не можете сократить это. Поэтому из этого должно быть ясно, что вы не на самом деле хотите убить и перезапустить свою программу, потому что тогда вы получите именно то поведение, которого вы не хотите. С конечным автоматом вы можете иметь одно состояние инициализации для холодного запуска, где система только что была включена, и второе состояние инициализации для теплого перезапуска.

О, и 6 нитей не очень много!:)

Ответ 9

В зависимости от того, что вы подразумеваете под "перезагрузкой" программы, я вижу несколько простых решений.

Один из них заключается в том, чтобы встроить всю вашу программу в некоторый класс "Программа", который по существу обеспечивает некоторый цикл, который имеет вашу надлежащую программу. Когда вам нужно перезапустить программу, вы вызываете статический общедоступный метод "Перезагрузка", который снова запускает цикл.

Вы также можете попытаться сделать системный вызов, который снова запустит вашу программу и выйдет. Как и было предложено в другом ответе, вы можете создать программу-оболочку для этой единственной цели (и проверить код возврата, чтобы узнать, нужно ли это выходить или перезаходить).

Другой простой вариант - использовать goto. Я знаю, что люди будут ненавидеть меня за то, что даже упомянули об этом, но позвольте ему взглянуть на это: мы хотим сделать простую программу, а не использовать красивый шаблон. Возвращение гарантирует уничтожение, поэтому вы можете создать программу с меткой в ​​начале, а некоторые функции "Перезапустить", которая только начинается с начала.

Какой бы вариант вы ни выбрали, хорошо документируйте его, чтобы другие (или вы в будущем) не использовали бы один WTF меньше.

PS. Как упоминалось alain, goto не будет уничтожать глобальные или статические объекты, то же самое можно было бы использовать для включения класса. Поэтому любой подход, который не включает запуск новой программы вместо текущего, должен либо воздерживаться от использования глобальных/статических переменных, либо принимать надлежащие действия для их повторной установки (хотя это может быть утомительным, как с добавлением каждого статического/глобального, вам необходимо изменить процедуру перезапуска).