是否可以从程序内重新启动程序?

时间:2016-10-13 13:37:02

标签: c++ application-restart

我正在开发一个C ++程序,使用一些函数,脚本或使程序重启的东西会很有用。这是一个很大的程序,所以手动重启所有变量将花费我很长时间......

我不知道是否有任何方法可以实现这一点或是否有可能。

9 个答案:

答案 0 :(得分:60)

如果你真的需要重新启动整个程序(即再次“关闭”和“打开”),那么“正确”的方法就是拥有一个单独的程序,其唯一目的就是重新启动你的主程序。 AFAIK很多具有自动更新功能的应用程序都以这种方式工作。因此,当您需要重新启动主程序时,只需调用“restarter”,然后退出。

答案 1 :(得分:44)

您可以在main功能中使用循环:

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

或者,如果您想要实际重启程序,请从线束中运行它:

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

其中42是返回代码,意思是“请重新启动”。

然后在程序中你的restart函数看起来像这样:

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

答案 2 :(得分:15)

在Unicies或其他任何地方execve,它的工作方式与the man page specifies类似,你只能...... 杀死我使用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%的CPU利用率。

在自我更新二进制文件的情况下,由于整个二进制文件(至少在Unix上喜欢,我不了解Windows)将在运行时复制到内存中,然后如果文件发生变化在execve(argv[0], ...调用之前的磁盘,将在磁盘上找到的新二进制文件,而不是旧的二进制文件,将被运行。

由于@CarstenS和@bishop在评论中指出,由于Unix的独特设计方式,开放文件描述符保存在fork / exec之间,因此顺序为了避免在调用execve时泄露打开的文件描述符,您应该在execve之前关闭它们,或者在第一个eFD_CLOEXEC / O_CLOEXEC打开它们地点 - 可以在Dan Walsh's blog找到更多信息。

答案 3 :(得分:13)

这是一个特定于操作系统的问题。在Windows中,您可以使用Application Restart APIMFC Restart Manager。在Linux中,您可以执行exec()

然而,大部分时间都有更好的解决方案。如其他答案所示,您可能最好使用循环。

答案 4 :(得分:9)

这听起来像是错误的方法,就像你所有的状态都是全局的一样,所以你重置所有内容的唯一明确方法(除了手动为每个变量分配&#34;默认&#34;值)是重启整个程序。

相反,您的状态应该保存在对象(类类型或其他类型)中。然后,您可以随意创建和销毁这些对象。每个新对象都有一个新的状态,默认为#34;值。

不要与C ++作斗争;用它!

答案 5 :(得分:6)

你可能需要一个循环:

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

每次需要重新启动时,请在循环中调用continue;,要结束程序,请使用break;

答案 6 :(得分:4)

当我开发实时系统时,我的方法通常是“派生的main()”,其中我编写了从真正的main()调用的所有代码,如:

main.cpp程序:

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

programmain.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系统。

答案 7 :(得分:2)

听起来我觉得你提出错误的问题,因为你对编码提出的问题不够充分,无法提出正确的问题。

这听起来像你要求的是如何编写一些代码,在未接来电时,它会循环回到初始状态并重新启动整个呼叫/位置序列。在这种情况下,您需要使用state machine。查看那是什么,以及如何编写一个。这是一个关键的软件概念,如果你的老师对他们的工作有任何好处,你应该知道。

作为旁注,如果您的程序需要5秒来初始化所有变量,那么当您重新启动变量时它仍会花费5秒。你不能快捷。因此,很明显你 实际上想要杀死并重启你的程序,因为那样你就会得到你所做的行为。 #39; t想要。使用状态机,您可以在冷启动时使用一个初始化状态,系统刚刚打开,第二个初始化状态用于暖启动。

哦,6个线程不是很多! :)

答案 8 :(得分:1)

根据“重新启动”程序的含义,我可以看到一些简单的解决方案。

一个是将整个程序嵌入到一些“程序”类中,它实际上提供了一个具有正确程序的循环。当您需要重新启动程序时,可以调用静态公共方法“Restart”来重新启动循环。

您还可以尝试进行系统特定的调用,以便再次启动程序,然后退出。 正如在其他答案中所建议的那样,您可以为此唯一目的创建一个包装程序(并检查返回代码以了解是退出还是重新启动)。

另一个简单的选择是使用goto。我知道人们会恨我甚至提到它,但让我们面对它:我们想制作简单的程序,而不是使用漂亮的样板。 Goto going back guarantees destruction,所以你可以在开头创建一个带有标签的程序,还有一些函数“Restart”就会回到开头。

无论您选择哪种方式,都要记录好,以便其他人(或您将来)使用一台WTF。

PS。正如alain所提到的,goto不会破坏全局或静态对象,同样可以用于封闭类。因此,任何不包括启动新程序代替当前程序的方法应该避免使用全局/静态变量,或者采取适当的操作来重新设置它们(尽管这可能是单调乏味的,如添加每个静态/全局,你需要修改重启例程。)