是否有可能从程序中重新启动程序?

我正在开发一个C ++程序,使用一些函数,脚本或者其他能让程序重启的东西是很有用的。 这是一个大的程序,所以手动重新启动所有的variables将需要很长时间…

我不知道是否有办法做到这一点,如果有可能的话。

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

你可以在main函数中使用一个循环:

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

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

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

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

然后在程序里面你的restartfunction看起来像这样:

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

在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是返回码)。

它既不recursion也不显式循环 – 相反,它只是调用自身,用自己的新版本replace自己的内存空间。

通过这种方式,堆栈将永远不会溢出,尽pipe所有先前的variables都将被重新声明,就像重新定位一样 – getchar调用可以防止100%的CPU使用率。

在自更新二进制文件的情况下,由于整个二进制文件(至less在Unix上,我不知道Windows)会在运行时被复制到内存中,如果文件在execve(argv[0], ...调用,在磁盘上find的新的二进制文件,不是相同的旧的,将被运行。

正如@CarstenS和@bishop在注释中指出的那样,由于deviseUnix的独特方式,打开的文件描述符保存在fork / exec ,因此为了避免跨execve调用泄露打开的文件描述符,你应该在execve之前closures它们,或者首先用eFD_CLOEXEC / O_CLOEXEC打开它们 – 更多信息可以在Dan Walsh的博客上find。

这是一个非常特定于操作系统的问题。 在Windows中,您可以使用应用程序重新启动API或MFC重新启动pipe理器 。 在Linux中你可以做一个exec()

但是大多数情况下有更好的解决scheme。 正如其他答案中所build议的那样,您最好使用循环。

这听起来像是错误的方法,就像你所有的状态都是全局的一样,所以你重置所有东西(除了为每个variables手动赋值“默认值”)的唯一明确的方法是重新启动整个程序。

相反,你的状态应该被保存在对象中(类的types或其他)。 随时随意创build和销毁这些对象,只要你喜欢。 每个新对象都具有“默认”值的新鲜状态。

不要反对C ++; 用它!

你可能需要一个循环:

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

每次需要重新启动时,请continue; 在循环内,并结束你的程序,使用break;

当我开发实时系统时,我的方法通常是一个“派生的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; } 

这样,每次我们决定退出程序,程序都会重新启动。

细节:所有的variables,全局variables和逻辑必须写在programMain()内部 – 除了重启控制之外, "main()"内部什么都没有。

这种方法适用于Linux和Windows系统。

这听起来像你问错误的问题,因为你不知道编码问题是否正确。

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

作为一个方面说明,如果你的程序需要5秒来初始化你所有的variables,当你重新启动时,它仍然需要5s。 你不能捷径。 所以从这个angular度来看,应该清楚的是,你并不是真的想杀死并重启你的程序,因为那样你就会得到你不想要的行为。 对于一个状态机,可以有一个初始化状态用于冷启动,系统刚刚打开,第二个初始化状态用于热启动。

哦,6线程不是很多! 🙂

根据“重新启动”程序的意思,我可以看到几个简单的解决scheme。

一个是将你的整个程序embedded到一些“程序”类中,从本质上说,它提供了一些有你的正确程序的循环。 当你需要重新启动程序时,你可以调用静态的公共方法“Restart”来重新启动循环。

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

另一个简单的select是使用goto 。 我知道人们会恨我,甚至提到它,但让我们面对现实:我们要做简单的程序,而不是使用漂亮的样板。 Goto回去保证破坏 ,所以你可以在开始时创build一个带有标签的程序,以及一些刚刚回到开头的“Restart”函数。

无论你select什么样的选项,都要logging下来,以便其他人(或你未来)将less用一个WTF。

PS。 如alain提到的, goto不会摧毁全局或静态对象,封闭类也是一样。 因此,任何不包括启动新程序来取代当前程序的方法都不应该使用全局/静态variables,或者采取适当的行动来重新设置它们(尽pipe这可能是单调乏味的,因为每个静态/全局,你需要修改重启例程)。

Interesting Posts