【问题标题】:Sharing the static global variable between two files在两个文件之间共享静态全局变量
【发布时间】:2020-11-03 06:51:40
【问题描述】:

我有一个构建到静态库 libdefine.a 中的 def.cc 文件:

def.h

#include<stdio.h>
#include <unistd.h>
 
 void testFunction();
 typedef struct _epoll_ctxt {
     int epfd;
     int last; 
 } epoll_ctxt;

def.cc

#include<stdio.h>
#include <unistd.h>
#include "def.h"

static int count = 0;
static epoll_ctxt g_epctxt;

 void testFunction() {
     g_epctxt.epfd = 5;
     printf("The epfd value is %d and val from  .h file", g_epctxt.epfd);
 }

我使用 def.o 创建了库 libdefine.a 我想在test.cc(驱动函数)中使用变量g_epctxt,所以我把代码写成

test.cc:

#include<stdio.h>
#include <unistd.h>
#include "def.h"

 extern epoll_ctxt g_epctxt;
 int main() {
     testFunction();
     g_epctxt.epfd = 8;
     printf("The epfd value is %d", g_epctxt.epfd);
     return 0;
 }

使用命令编译:gcc test.cc -L。 -ldefine 并得到以下错误:

/tmp/ccdr4Xi5.o:在函数“主”中: test.cc:(.text+0x10): 对“g_epctxt”的未定义引用 test.cc:(.text+0x19): 对“g_epctxt”的未定义引用 collect2: ld 返回 1 个退出状态

谁能帮我看看我错过了什么。

【问题讨论】:

  • 尝试谷歌变量声明中的static 是什么意思。
  • @MikeCAT,我已经有一个很大的代码库,所以我简化了问题并输入了示例格式。我想在另一个 .cc 文件中使用这些全局变量
  • 不暴露全局变量,不如封装需要的行为,然后暴露接口?
  • 为什么同时标记 C 和 C++?它们是两种不同的语言
  • “静态但全局”就像说“猫但狗”或“红色但绿色”。使用static 的真正目的是阻止变量全局暴露。所以实际的问题是你的程序设计。请改用 setter/getter 函数。

标签: c++ compiler-errors linker


【解决方案1】:

def.cc 中,以下声明表示具有内部链接的变量:

static epoll_ctxt g_epctxt;

C++ 标准section 6.6 §3.1:

具有命名空间范围的名称如果是以下名称,则具有内部链接

  • 显式声明的变量、变量模板、函数或函数模板static

此外,在section 6.6 §2.3:

当名称具有内部链接时,它所表示的实体可以被同一翻译单元中其他范围的名称引用。

因此,当您在翻译单元(在本例中为 def.cc 文件)中声明 static 全局变量时,您只能在同一翻译单元内引用它。具有内部链接的名称也被标准称为TU-localstranslation-unit locals)。

基于section 6.6 §18,我们可以指出您的程序格式错误:

如果出现在一个翻译单元中的声明命名了在另一个不是标头单元的翻译单元中声明的 TU-local 实体,则程序格式错误。

您似乎只想在所有其他翻译单元中拥有变量 g_epctxt 的单个实例。因此,您会希望变量具有外部链接。为此,您只需在不带说明符 staticdef.cc 中定义变量:

// def.cc

// Global variables have external linkage by default
epoll_ctxt g_epctxt;

不过,在头文件 (def.h) 中也声明这种类型的变量 extern 是一种很好的做法。这样你就不必每次使用时都重新声明变量,而且还明确了变量是设计用于其他翻译单元的:

// def.h
extern epoll_ctxt g_epctxt;

使用上面的extern 声明,您应该从test.cc(和其他.cc 文件)中删除现在多余的g_epctxt 声明:

// test.cc

// This is redundant and should be removed
extern epoll_ctxt g_epctxt;

您也可以这样想这个解决方案:如果您想更改变量g_epctxt 的名称或类型,您是只想在def.ccdef.h 中进行,还是在@987654343 中进行@ 以及声明它的所有不同的 .cc 文件。

【讨论】:

    猜你喜欢
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    • 2019-08-17
    • 1970-01-01
    • 2015-03-28
    • 1970-01-01
    • 1970-01-01
    • 2010-11-23
    相关资源
    最近更新 更多