2010-07-21 25 views
0

我在一个文件中获得了一个函数,用于单个函数调用。但是,因为它依赖于这个文件中的很多静态声明(我没有创建这个文件,而且它很大程度上需要修改)。它不适用于多个函数调用。为一个函数强制一个新的地址空间(使静态变量非静态)

有没有办法使每个函数调用不知道以前的调用或当前调用? 实际上为每个函数调用强制一个新的地址空间。

//file inner.c 
#include <stdio.h> 

static int counter =1; 

int incIt(int a){ 
    counter += a; 
    return counter; 
}; 

和主文件

//file outer.c 
#include <stdio.h> 
#include "inner.h" 

int main(){ 
    fprintf(stderr,"first: %d\n",incIt(5)); 
    fprintf(stderr,"second: %d\n",incIt(7)); //this should be independent of previous calls. 
    return 0; 
} 

编译像

gcc -c inner.c 
gcc outer.c 

感谢

+2

你预计第二次电话会返回什么? – Arkadiy 2010-07-21 16:54:49

+4

不要使用静态变量? – Stephen 2010-07-21 16:59:13

+0

在你的例子中,问题不在于使用静态变量,而在于使用全局变量(文件范围)。 – schot 2010-07-21 17:28:17

回答

-1

你可以尝试装卸对象从编译inner.c与dlopen。

3

您通过使所有变量本地(即通过给它们自动存储持续时间)强制新的地址空间。这就是自动变量的全部目的 - 每个调用都有自己独立的一组局部变量。

通过声明变量static您正在朝相反的方向移动 - 您明确要求编译器在每次调用中使用相同的变量。所以,决定你在做什么,然后去做。

如果你不能修改变量和/或函数声明,那么你运气不好。它不能做到。

3

如果您希望代码是可重入的,则必须避免使用全局变量或文件静态变量。在C++中,您将变量包含在一个类(带有构造函数)中,并为每个独立的一组操作实例化类。

在C中,你模拟了你将在C++中做什么。

对于例如,在C++:

#include <stdio.h> 
class Counter 
{ 
    int counter; 
public: 
    Counter() : counter(1) { } 
    int incIt(int a) { counter += a; return counter; } 
}; 

int main() 
{ 
    Counter c1; 
    Counter c2; 
    printf("First: %d\n", c1.incIt(5)); 
    printf("Second: %d\n", c2.incIt(7)); 
    return 0; 
} 

或者,在C:

#include <stdio.h> 
typedef struct Counter 
{ 
    int counter; 
} Counter; 

void initCounter(Counter *c) { c->counter = 1; } 
int incIt(Counter *c, int a) { c->counter += a; return c->counter; } 


int main() 
{ 
    Counter c1; 
    Counter c2; 
    initCounter(&c1); 
    initCounter(&c2); 
    printf("First: %d\n", incIt(&c1, 5)); 
    printf("Second: %d\n", incIt(&c2, 7)); 
    return 0; 
} 

如果你真的不能更改源代码,那么你被卡住。一种可能性是将你需要的代码提取到一个允许重入设计的新源文件中(根据需要重新命名函数和变量)。使用新的代码。如果没有这样做,你就会陷入困境 - 你必须回到供应商那里,并恳求做出必要的改变。

2

为每次调用分配一个新的子进程。

2

对代码中出现的问题最简单的解决方案是添加一个新函数来处理重置计数器。

很明显,这并没有让代码重入,但可能正是你需要清除过去的历史。

-1

这里的答案,如果一个同事问我,我会给:

不要那样做!

0

“我想改变世界,但他们只是不会给我的源”

#define static 

对于那些在功能申报,并手动将在全局范围内他们休息。 这并不意味着它仍然可以按预期工作。

0

随着给定的要求,我提供这个便携式解决方案。该解决方案将模仿局部变量。用替换类型替换实例化的模板类,替换静态或全局变量中遇到的所有类型。模板类将存储替换类型的堆栈。安排一些事情,以便您可以通过一次调用来推送或弹出此模板类的所有实例的堆栈。一旦进入您的传统功能推送,离开流行音乐。

这个解决方案不是非常容易实现,但应该允许现有的结构保持复杂,因为它似乎不采用分叉或动态加载等不可移植的方式。

不过,我认为如果旧代码不应该被重写,以免您未来的痛苦,我们应该退一步,重新考虑一下。

3

此声明“是否有某种方法让每个函数调用不知道以前的调用或当前调用?”言下之意,这可能为你工作:

int incIt(int a){ 
    int localCounter = 1; 
    localCounter += a; 
    return localCounter; 
}; 
0

丑陋的黑客警告:获取指向第一个静态/内存全球性的,指针到最后。编写一个包装函数,它可以复制静态块以便每次调用都获得它自己的一组静态/全局变量。假设所有有趣的静态/全局变量在内存中都是连续的......正确的解决方案是“像Jonathan Leffler描述的那样更改代码”。