【问题标题】:Pointer to a global static variable - not safe?指向全局静态变量的指针 - 不安全?
【发布时间】:2013-10-27 20:11:17
【问题描述】:

我有一个文件,其中有一个全局数组

static char name[6];

还有一个函数

static char* gen_name(char* dest, const size_t len) {
    for (int i = 0; i < len - 1; ++i)
        dest[i] = 'A' +  (genrand_uint32() % ('Z' - 'A'));
    dest[len - 1] = '\0';
    return dest;
}

指向名称的指针然后存储在不同头文件中的全局变量中,该变量不是静态的。

this_name = gen_name(name, sizeof name);

当另一个文件中的函数使用这个指针时,它在 Linux 上运行良好,但是当我在微控制器上运行相同的代码时,它会打印垃圾。 当我删除 static 关键字时,它工作正常。

为什么会这样?

什么时候应该使用static? 我以为我应该将所有未在文件外使用的变量和函数声明为static,这是错误的吗?

【问题讨论】:

  • 显示变量name填入的代码。
  • static char* gen_name(...) 并没有按照你的想法去做。
  • @RaymondChen 怎么样? (注意:for 标头之后第二行的缩进令人困惑,但不影响编译器如何查看它。)
  • 对我来说,这看起来像是一个过度活跃的编译器,它以不应该的方式优化代码。使用-O0 编译时问题是否仍然存在?
  • @NikosC。看起来 OP 认为它是一个返回指向静态字符的指针的函数。但实际上它是一个返回char指针的静态函数。

标签: c


【解决方案1】:

当你在标题中声明变量时,你是否记得将它标记为extern?你需要这样做,否则你只会在每个包含标题的文件中获得一个新变量。请记住,#include 只是一个复制粘贴工作;预处理器只是将头文件中的文本插入到包含发生的位置。如果头文件中的文本是char name[6],那么这就是你得到的;源代码中的文本为 char name[6],导致变量 name 与您在其他源文件中的变量无关。

如果您将其标记为extern,则链接器将抱怨找不到该符号。这意味着name 的定义不能是static,因为这会导致链接器无法找到它。

所以,在你的头文件中,你需要这个声明:

extern char name[6];

在你的源文件中,你需要这个定义:

char name[6];

并回答实际问题:是的,它非常安全。

【讨论】:

  • 谢谢,我不知道extern部分,现在我有一个带有extern char *this_name;的标题,对应的带有char *this_name;的.c文件和开头的.c文件,与static char name[6];,名称的实际内存位置。但是,当我声明名称为静态时,this_name 会打印垃圾,而当我不使用 static 时不会。
  • 如果您可以生成一个只有几行代码的最小程序仍然存在问题,那将有所帮助。因为现在,您的代码中可能有任何其他内容与name 的内容相混淆。
【解决方案2】:

原来是由不同线程中的堆栈溢出引起的,将其标记为静态会将其放入 bss 部分,就在会溢出的堆栈后面。

【讨论】:

    【解决方案3】:

    静态关键字与函数和变量的含义不同。

    函数默认为“extern”,即它们的入口点由编译器公开,因此链接器可以找到它们,并且可以从任何已编译的模块中调用它们。 如果你在函数声明前加上“static”,函数将不再是公共的,即它只会在同一个源模块中被知道。

    'static' 关键字在用于变量(*)时具有非常不同的含义。它使它们不可更改。 当你说'static char name[6]'时,你是在告诉编译器你无意改变'name'的值。

    在 PC 上运行的 Linux 上,这并不意味着什么。你告诉编译器你不会改变这个值,然后你就改变它。你撒谎。没什么大不了的。

    一些微控制器具有内部闪存,可用于从中运行代码,并在其中保存固定(恒定!)数据。 编译器和链接器使用您的“名称”不会更改并将变量留在闪存中的承诺。 你可以想象当你尝试改变它时会发生什么(不会发生)。

    更准确地说,编译器会将所有静态变量放在类似 .const 的部分中,然后链接器会将该部分放入闪存中。

    (*) 有一种方法可以查看“const”,这使得它在用于变量和函数时具有相同的含义。这里不重要。

    【讨论】:

      猜你喜欢
      • 2010-10-02
      • 2014-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-11
      • 2021-11-11
      • 2014-04-19
      • 1970-01-01
      相关资源
      最近更新 更多