我正在开发一个c++程序,使用一些函数,脚本或使程序重新启动的东西将是有用的。这是一个很大的程序,所以手动重新启动所有变量将花费我很长时间……
我不知道是否有任何方法来实现这一点,或者如果它是可能的。
如果你真的需要重新启动整个程序(即再次"关闭"one_answers"打开"),"适当"的方法是有一个单独的程序,其唯一目的是重新启动你的主程序。据我所知,很多带有自动更新功能的应用程序都是这样工作的。因此,当您需要重新启动主程序时,只需调用"restarter"程序,然后退出即可。
您可以在main
函数中使用循环:
int main()
{
while(!i_want_to_exit_now) {
// code
}
}
或者,如果您想重新启动程序,可以从线束中运行它:
program "$@"
while [ $? -e 42 ]; do
program "$@"
done
其中42
为返回码,表示"restart, please"。
然后在程序中你的restart
函数看起来像这样:
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: %sn", 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
之前关闭它们,或者首先使用e
, FD_CLOEXEC
/O_CLOEXEC
打开它们——更多信息可以在Dan Walsh的博客中找到。
这是一个非常特定于操作系统的问题。在Windows中,您可以使用应用程序重启API或MFC重启管理器。在Linux中,你可以输入exec()
然而,大多数时候有更好的解决方案。你最好使用循环,就像其他答案中建议的那样。
这听起来像是错误的方法,就像你所有的状态都是全局的,所以唯一明确的重置所有东西的方法(除了手动为每个变量分配"默认"值)是重新启动整个程序。
相反,你的状态应该保存在对象中(类类型或其他)。然后,您可以随时自由地创建和销毁这些对象。每个新对象都有一个带有"默认"值的新状态。
不要对抗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;
}
这样,每次我们决定退出程序时,程序将重新启动。
细节:所有的变量,全局变量和逻辑必须写在programMain()
中- "main()"
中除了重启控制之外没有任何内容。
此方法在Linux和Windows系统中都有效。
听起来你问错了问题,因为你对编码的了解不够,无法提出正确的问题。
听起来你想要的是如何编写一些代码,在未接来电时,它循环回到初始状态并重新启动整个呼叫/定位序列。在这种情况下,您需要使用状态机。查一下这是什么,以及如何写。这是一个关键的软件概念,如果你的老师擅长他们的工作,你应该知道它。
作为旁注,如果你的程序初始化所有变量需要5秒,那么当你重新启动它时,它仍然需要5秒。你不能抄近路。因此,很明显,你并不是真的想要杀死并重新启动你的程序,因为这样你就会得到你不想要的行为。对于状态机,您可以有一个初始化状态用于冷启动(系统刚刚打开),第二个初始化状态用于热重启。
哦,6个线程不是很多!:)
根据你所说的"重新启动"程序的意思,我可以看到一些简单的解决方案。
一种是将整个程序嵌入到某个"program"类中,该类本质上提供了一些循环,其中包含适当的程序。当你需要重新启动程序时,调用静态公共方法"restart"重新开始循环。
您也可以尝试进行系统特定的调用,重新启动程序并退出。正如另一个答案所建议的那样,您可以为此目的创建一个包装程序(并检查返回代码以知道是退出还是重新启动)。
另一个简单的选择是使用goto
。我知道人们会因为我提到这一点而讨厌我,但让我们面对现实:我们想要制作简单的程序,而不是使用漂亮的样板。Goto返回保证了销毁,所以你可以创建一个在开始时带有标签的程序,并使用"Restart"函数返回到开始。
无论您选择什么选项,请将其记录好,以便其他人(或将来的您)可以少使用一个WTF。
p。如前所述,goto
不会销毁全局或静态对象,也不会销毁封闭类。因此,任何不包括在当前程序的位置启动新程序的方法都应该避免使用全局/静态变量,或者采取适当的措施来重新设置它们(尽管这可能很繁琐,因为添加了每个静态/全局变量,您需要修改重新启动例程)。
简单而干净的方法是将未使用的数据引脚添加到RESET引脚并将其设置为低复位!: -)