2

我正在重构“意大利面条代码”C 模块以在多任务 (RTOS) 环境中工作。

现在,有很长的函数和许多不必要的全局变量。

当我尝试用局部变量替换仅存在于一个函数中的全局变量时,我陷入了困境。每个全局变量都表现得像本地“静态” - 例如,即使您退出并重新进入函数,也保持其值。

对于多任务处理,“静态”本地变量是全局变量中最差的。它们使函数不再重新输入。

有一种方法可以检查函数是否在保留变量值重新进入而不跟踪所有逻辑流的情况下进行中继?

4

6 回答 6

8

简短的回答:不,没有任何方法可以根据局部变量的声明是否为静态来自动判断函数的行为是否不同。您只需检查在原始代码中使用全局变量的每个函数的逻辑。

但是,如果用静态局部范围变量替换全局变量意味着该函数不是可重入的,那么当它是全局时它也不是可重入的。因此,我认为将全局变量更改为静态局部范围变量不会使您的函数比开始时的可重入性更少。

如果全局确实仅在该范围内使用(当您删除全局时编译器/链接器应确认),则行为应该接近相同。初始化时可能会或可能不会出现问题,我不记得标准是怎么说的:如果静态初始化在 C 中与在 C++ 中发生的时间相同,那么当执行第一次到达声明时,您可能已经更改了并发安全函数变成了非并发安全函数。

确定一个函数是否可以安全地重入还需要查看逻辑。除非标准另有说明(我没有检查过),否则函数不会仅仅因为它声明一个静态变量而自动不可重入。但是,如果它以任何重要的方式使用全局或静态,您可以假设它是不可重入的。如果没有同步,那么假设它也是非并发安全的。

最后,祝你好运。听起来这段代码离你想要的地方还有很长的路要走......

于 2008-09-25T16:57:34.203 回答
1

如果你的全局变量真的只用在一个函数中,那么将它们变成静态局部变量不会有任何损失,因为它们无论如何都是全局的,这使得使用它们的函数不可重入。通过限制变量的范围,您会有所收获。

您应该对仅在一个函数中使用的所有全局变量进行更改,然后检查每个静态局部变量以查看是否可以将其设为非静态(自动)。

规则是:如果变量在设置之前在函数中使用,则保持静态。

可以自动本地化的变量示例(您可以将“ int nplus4;”放在函数内(您不需要将其设置为零,因为它是在使用前设置的,如果您在设置它之前实际使用它,这应该会发出警告,一个有用的检查):

int nplus4 = 0;         // used only in add5
int add5 (int n) {
    nplus4 = n + 4;     // set
    return nplus4 + 1;  // use
}

var在nplus4使用之前设置。以下是一个应该通过static int nextn = 0;在函数中放置“”来保持静态的示例:

int nextn = 0;             // used only in getn
int getn (void) {
    int n = nextn++;       // use, then use, then set
    return n;
}

请注意,它可能会变得棘手,“ nextn++”不是设置,而是使用和设置,因为它等效于“ nextn = nextn + 1”。

另一件需要注意的事情:在 RTOS 环境中,堆栈空间可能比全局内存更有限,因此在将大的全局变量(例如“ char buffer[10000]”)移动到函数中时要小心。

于 2008-09-26T06:33:19.140 回答
1

如果您的编译器在初始化之前使用变量时会警告您,请使可疑变量成为本地变量,而不在其声明中为其分配值。

如果不更改其他代码,任何发出警告的变量都不能成为本地变量。

于 2008-09-25T17:01:51.587 回答
1

将全局变量更改为静态局部变量会有所帮助,因为修改的范围已经缩小。但是,并发问题仍然是一个问题,您必须通过锁定访问这些静态变量来解决它。

但是你想要做的是将变量的定义推入它用作本地的最高范围,然后将它作为参数传递给任何需要它的东西。这显然需要大量工作(因为它具有级联效应)。您可以将类似需要的变量分组到“上下文”对象中,然后将它们传递出去。

请参阅设计模式封装上下文

于 2008-09-25T17:14:30.497 回答
0

请举例说明您所谓的“全局”和“局部”变量

int global_c; // can be used by any other file with 'extern int global_c;'

static int static_c; // cannot be seen or used outside of this file.

int foo(...)
{
   int local_c; // cannot be seen or used outside of this function.
}

如果您提供一些代码示例,说明您拥有的内容和更改的内容,我们可以更好地回答这个问题。

于 2008-09-25T16:57:17.527 回答
0

如果我正确理解您的问题,您担心的是全局变量从一个函数调用到下一个函数调用保留其值。显然,当您转而使用普通的局部变量时,情况并非如此。如果您想知道更改它们是否安全,我认为您除了阅读和理解代码之外别无选择。简单地对相关变量的名称进行全文搜索可能是有益的。

如果你想要一个不完全安全的快速而肮脏的解决方案,你可以改变它,看看有什么问题。我建议确保你有一个可以在源代码控制中回滚的版本,并提前设置一些单元测试。

于 2008-09-25T17:05:41.563 回答