我有一个我需要重用的旧版C Linux应用程序。该应用程序使用了许多全局变量。我想重用这个应用程序的main方法并在循环中调用它。我发现当我在循环中调用main方法(重命名为callableMain)时,应用程序行为不一致,因为在上一次迭代中设置的全局变量值会影响新迭代中的程序流。
我想要做的是在执行新迭代之前将所有全局变量重置为默认值。
例如,原始程序就像这样OriginalMain.C
#include <stdio.h>
int global = 3; /* This is the global variable. */
void doSomething(){
global++; /* Reference to global variable in a function. */
}
// i want to rename this main method to callableMain() and
// invoke it in a loop
int main(void){
if(global==3) {
printf(" All Is Well \n");
doSomething() ;
}
else{
printf(" Noooo\n");
doNothing() ;
}
return 0;
}
我想按如下方式更改此程序:
我更改了上面的文件,将main()重命名为callableMain()
我的新主要方法如下:
int main(){
for(int i=0;i<20;i++){
callableMain();
// this is where I need to reset the value of global vaiables
// otherwise the execution flow changes
}
}
是否可以在调用main()之前将所有全局变量重置为值?
简短的回答是,没有神奇的api调用会重置全局变量。全局变量必须被缓存和重用。
答案 0 :(得分:8)
我会将其作为子进程调用,根据需要修改其输入和输出。让操作系统为你做脏事。
我们的想法是将遗留程序与新程序隔离开来,将其归入自己的程序。然后你们两者之间就分开了。此外,每次运行旧程序时都会将其重置为干净状态。
首先,修改程序,使其从文件中读取输入数据,并将其输出以机器可读的格式写入另一个文件,文件在命令行中给出。
然后,您可以创建命名管道(使用mkfifo
调用)并使用system
调用旧程序,并在命令行上传递命名管道。然后你输入它的输入并读回它的输出。
我不是这方面的专家;可能有更好的方法来进行IPC。这里的其他人提到fork
。但是,分离遗留代码并将其作为子进程调用的基本思想可能是最好的方法。
答案 1 :(得分:5)
当你认为全局状态处于良好状态时,你可以在某个早期点fork(2)
,然后让孩子在管道上等待某些工作要做。这需要将任何已更改的状态或至少结果写回父进程,但会将您的工作者与主要控制进程分离。
事实上,fork()
至少两次可能是有意义的,一次设置一个工作控制器并保存初始化(但不是太初始化的:-)全局状态,然后让这个工作器控制器{{ 1}}再次为你需要运行的每个循环。
更简单的变体可能只是修改代码,以便进程可以以“工作模式”启动,然后使用fork()
或fork()
在顶部启动应用程序,但是将其置于从模式的参数。
答案 2 :(得分:3)
有一种方法可以在某些平台/编译器上执行此操作,您基本上在调用main()
之前执行编译器执行的相同初始化。
我已经为TI DSP做了这个,在这种情况下,我有一个全局变量映射到特定内存部分的部分,并且有可用的链接器指令声明指向本节开头和结尾的变量(所以你可以memset()
在开始初始化之前整个区域为零)。然后,编译器提供了一个记录列表,每个记录包括一个地址,数据长度和要复制到地址位置的实际数据。所以你只需遍历记录并在目标地址中memcpy()
来初始化所有全局变量。
特定于编译器,所以希望您使用的编译器允许您执行类似的操作。
答案 3 :(得分:1)
简而言之,没有。在这个例子中我要做的是创建定义,如果你愿意,然后使用它们来重置全局变量。
基本上
#define var1 10
int vara = 10
等等......基本C对吗?
然后,您可以继续将重新初始化包装在一个方便的函数中=)
答案 4 :(得分:0)
我认为你必须改变你看待问题的方式。
声明callableMain()内部的callableMain()所使用的所有变量,因此它们不再是全局变量,并且在执行该函数后被销毁,并在调用callableMain()时再次使用默认值创建下一次迭代。
修改强>
好的,如果你有callableMain()的源代码,你可以做什么:在函数的开头,添加一个检查来验证它是否第一次调用它的函数。在此检查中,您将所有全局变量的值复制到另一组 static 变量(根据需要命名)。然后,在函数体上用你创建的静态变量替换全局变量的所有出现。
这样,您将保留所有全局变量的初始值,并在callableMain()的每次迭代中使用它们。这对你有意义吗?
void callableMain()
{
static bool first_iter = true;
if (first_iter)
{
first_iter = false;
static int my_global_var1 = global_var1;
static float my_global_var2 = global_var2;
..
}
// perform operations on my_global_var1 and my_global_var2,
// which store the default values of the original global variables.
}
答案 5 :(得分:0)
for (int i = 0; i < 20; i++) {
int saved_var1 = global_var1;
char saved_var2 = global_var2;
double saved_var3 = global_var3;
callableMain();
global_var1 = saved_var1;
global_var2 = saved_var2;
global_var3 = saved_var2;
}
或许你可以找出全局变量从哪里开始memcpy
。但是在开始循环时我总是会畏缩...
for (int i = 0; i < 20; i++) {
static unsigned char global_copy[SIZEOFGLOBALDATA];
memcpy(global_copy, STARTOFGLOBALDATA, SIZEOFGLOBALDATA);
callableMain();
memcpy(STARTOFGLOBALDATA, global_copy, SIZEOFGLOBALDATA);
}
的
答案 6 :(得分:0)
如果您不想重构代码并封装这些全局变量,我认为您可以做的最好的事情是定义一个重置函数,然后在循环中调用它。