为什么全局变量在单线程,非os,嵌入式应用程序中是坏的

时间:2009-05-16 18:09:06

标签: c embedded global-variables

我看到使用全局变量的大多数异议都有意义,因为它们引用了多线程,线程安全等问题。

但是在一个小的,单线程的,非操作系统的情况下,你有什么异议?就我而言,如果重要的话,我正在用“C”编写我的嵌入式系统。我也是该产品的唯一开发人员。

为什么消除全局变量会使我的代码变得更好?

(在阅读了几个响应之后,我意识到我也应该指出这个系统没有动态内存分配(例如malloc)。所有内存都是在编译时静态分配的。)

13 个答案:

答案 0 :(得分:48)

不会。

全局变量的两个基本问题是简单地混淆命名空间,以及“没有人”对它们“控制”的事实(因此潜在的冲突和与多个线程的冲突)。

“全局性很糟糕”,就像几乎所有其他计算机编程习惯都是一个指导原则,而不是一个硬性规则。当制定这些“规则”时,最好不要简单地通过死记硬背来理解规则制定背后的情况和动机。不要盲目地接受它们。

在您的情况下,您似乎了解系统的性质和规则的参数,并认为它不适用于这种情况。你是对的,事实并非如此。

所以,不要担心。

答案 1 :(得分:18)

这是一篇很好的文章,提供了原因Why global variables are Bad

为什么在不必要时应避免使用全局变量?

  

非本地化 - 当各个元素的范围有限时,源代码最容易理解。全局变量可以由程序的任何部分读取或修改,使得难以记住或推理每种可能的用途。   无访问控制或约束检查 - 程序的任何部分都可以获取或设置全局变量,并且可以轻松地删除或忘记有关其使用的任何规则。

     

隐式耦合 - 具有许多全局变量的程序通常在这些变量之间存在紧密耦合,以及变量和函数之间的耦合。将耦合项目分组为有凝聚力的单元通常会带来更好的计划。

     

内存分配问题 - 某些环境具有内存分配方案,使得全局变量分配变得棘手。在“构造函数”具有除分配之外的副作用的语言中尤其如此(因为,在这种情况下,您可以表示两个全局变量彼此相互依赖的不安全情况)。此外,当动态链接模块时,可能不清楚不同的库是否有自己的全局变量实例或者是否共享全局变量。

     

测试和限制 - 使用全局变量的源更难以测试,因为在运行之间无法轻易建立“干净”的环境。更一般地,利用未明确提供给该源的任何类型的全局服务的源很难以相同的原因进行测试。

添加全局变量非常简单。养成宣布它们的习惯很容易。它比想到一个好的设计要快得多。

全局变量并不像你想象的那么糟糕,只要不必要就应该避免它们。全局变量可以很好地用于在程序中使用的变量,确保记住您始终必须跟踪变量的变化位置;但对于那些往往仅在程序的有限部分内使用的变量,有充分的理由避免将其全局化。

答案 2 :(得分:18)

全局变量不一定是坏的,就像宏不一定是坏的一样,浓缩铀也不一定是坏的。只要你有意识地决定给定设计选择的利弊,你应该没事。

反对全局变量的一些参数是:

  1. 他们违反了良好的面向对象设计
  2. 它们使您的代码难以进行单元测试,因为您无法在不设置代码期望看到的所有全局变量的情况下测试单个代码块
  3. 它们会增加代码中的耦合:一个代码块中的操作可能会通过共享的全局变量以不可预测的方式影响另一个代码块中的内容

全局变量的一些争论者

  1. 它们可以轻松地在许多功能之间共享单个资源
  2. 他们可以使代码更容易阅读

如果在您的设计中,全局变量有意义,并且可用于使您的代码更易于阅读或更易于维护,而无需为随机错误和测试头痛做好准备,那么一定要使用它们。

我为嵌入式微控制器编写了很多C代码,并且我一直使用全局变量。在这样一个僵化的系统中,全局变量是有意义的。我知道潜在的缺点,但我已经分析了它的优点和缺点。缺点和我编写我的代码,以防止主要陷阱。

结论:没有严格的规则。根据您拥有的最佳信息,为您的特定项目或平台做出最佳决策。

答案 3 :(得分:8)

因为它可以最大限度地减少耦合。您的系统现在可能很小,但如果您继续工作,可能会变得不那样。

答案 4 :(得分:7)

在用C编写的小型嵌入式应用程序中,全局变量是必需的。例如,您需要使用全局变量才能在中断服务程序和另一个模块之间传递信息。这些是一些提示,可以帮助您在嵌入式应用程序中有效地使用全局变量:

  • 区分静态变量和全局变量。静态变量可以在同一个C文件中的所有函数中使用。它们相当于C ++类中的私有成员。在C中,你必须自己完成编译器的工作。使用static关键字可以避免在模块外部意外使用变量并明确其范围。您可能希望在变量前加上模块的名称。

  • 遵循全局变量的命名约定(由许多C文件使用)。明确表明它们是全球性的。

  • 如果您需要大量全局变量,请考虑将它们捆绑在一个结构中。

  • 必要时使用volatile关键字。如果ISR修改了全局变量,则需要这样做。

答案 5 :(得分:5)

使用全局变量的代码难以维护。由于维护者必须先找到系统中变量的每一个用法,然后才能准确地知道变量的作用。由于这会减慢维护速度,因此应尽可能避免使用。就是这个`

答案 6 :(得分:2)

这是一个范围问题。我们的开发人员喜欢制作全局变量来执行本地概念。它使得这些变量的使用更难以跟踪,因此在使用它们时更容易出错。

您也可以将钱包放在前门廊上,但之后您对访问它的人的控制程度要低得多。

话虽如此,Global变量有一些有效用途,但与其他任何值得遵循的规则一样。这是例外,不是正常情况。他们现有的指出他们有用。

如果您决定使用全局变量,请尝试对它们进行评论,并为它们指定好名称。当人们制作全球变量如“bool bIsFound;”

时,我真的很烦

我们要在代码审查中评估每个新的全局变量,看看是否有更好的方法。

答案 7 :(得分:1)

简短的回答是,全球变量在历史上一直是微妙错误的根源。但是(戴上我的功能程序员帽子)所有变量都是微妙的错误来源。

基本上,全局变量意味着你不能使用变量的值查看一段代码,并且知道它将要做什么,而不知道变量值在过去所做的每一段代码。

答案 8 :(得分:1)

在您的情况下,或许全局变量不是。另一方面,你需要它们吗?使用它们可以获得什么?

即使在你的情况下,全局变量也很难弄清楚应用程序的状态。这可能会阻碍调试,并可能导致细微的错误。

全局变量也使测试更加困难。它们会增加您在测试期间可能希望避免的外部代码的依赖性。

但最后,在使用C编程时,全局变量很难避免。在更高级的语言中,全局变量在大多数情况下都是毫无意义的。使用它们并不会使您的代码更清晰。

在C语言中,有很多情况下全局变量只是最好,最简单,最干净的解决方案。

因此,在您的情况下,根据具体情况进行处理。您可能最终会得到一些全局变量,但是除非您确定它实际上是最好的解决方案,而不仅仅是现在,但是从现在起必须调试代码或制作应用程序多线程。

答案 9 :(得分:0)

对于全局变量,通常很难知道它们何时何地更新以及哪些代码更新了该变量。无法控制谁可以更新它或以何种方式更新变量。

跟踪应用程序是否很小并不难 - 但是应用程序变得越大,并且您拥有的全局变量越多,应用程序代码就越像意大利面。

简而言之 - 它成为维护和调试的噩梦。

答案 10 :(得分:0)

问题是追踪上一段代码的哪一部分修改了全局状态。通常,您希望将变量保持在尽可能小的范围内,以便您可以更轻松地对其进行推理。

答案 11 :(得分:0)

浮现在脑海中的一个原因是未来的证明。您现在可能是您产品上唯一的开发人员,但可以想象其他人将在以后维护它。当然,在您的特定情况下,这可能不是真的。

虽然您的产品现在可能很小而且整洁 - 使用全局变量并不会使整体设计复杂化或损害可读性 - 可以说产品不会变得更大或者被整合到另一个产品中?并且上帝禁止另一个维护者/开发人员来解决你对全局变量的使用。

当然,您现在可以决定使用全局变量,当项目变得越来越复杂时,请返回并重写其中的部分内容,但为什么要强迫自己进行额外的工作呢?你更有可能(如果你还记得全球变量)决定做那项工作太费劲了,让设计出现:此时你遇到了麻烦!

所以,拯救你自己的头痛和设计,着眼于未来。现在所需的工作可能会使将来生活更轻松。

如果这不能说服你,那么想象一下,作为开发这个项目的开发人员,他们的代码在最高法院面前被发现错误并且犯了错误的编程习惯:Buggy breathalyzer code reflects importance of source review

答案 12 :(得分:0)

将大多数变量保持在本地并缩小其范围有助于促进更好的编程实践。它还降低了错误地更改变量的风险,并且必须追踪功能以寻找意外或非显而易见的后果。我相信它也使代码更易于阅读和维护,因为与特定代码段相关的大多数变量都是在附近定义和初始化的。否则,我似乎经常回顾定义所有golbals的代码部分。我确实使用了一些全局变量,但主要用于将配置信息传递给子模块。