C++全局类变量未被创建

4
我正在查看一段创建全局类变量的代码。这些类的构造函数调用符号表单例并将this指针添加到其中。
在Keywords.cpp文件中。
class A : class KeyWord
{
  A() { add(); }
} A def;

同样地,关键字B、C等也是如此。
void KeyWord::add()
{
 CSymbolCtrl& c = CSymbolCtrl::GetInstance();
 c.addToTable(this);
}

这些翻译单元被编译成一个库。当我使用 "dumpbin" 命令查看这个库时,我可以看到 ADef、BDef 等的动态初始化函数。

但是在可执行文件中,当我调用 CSymbolCtrl 实例时,在其映射中并没有找到 ADef、BDef 等内容。当我在 add() 函数中设置断点时,它没有被触发。难道链接器会忽略 ADef、BDef 等因为它们没有被任何地方引用吗?

}


1
你能使用可编译的样例代码吗? - Fred Nurk
3个回答

3

来自标准文档1.9程序执行,

4) 这个规定有时被称为“仿佛”规则,因为只要程序的可观察行为表现得就好像遵守了该要求一样,实现就可以自由地忽略国际标准的任何要求。例如,如果实现可以推断出一个表达式的值没有被使用并且不会产生影响程序可观察行为的副作用,那么实际上的实现不需要评估该表达式的一部分。

所以,是可能的,是的。


1
从你的问题中并不太清楚,但是你是否实际上将编译后的目标文件包含在链接中呢?仅仅将一个文件放入库中并不能使它被包含在最终程序中。根据定义,来自库的文件只有在解决未解决的外部符号时才会被包含在可执行文件中。如果你想让一个目标文件成为最终可执行文件的一部分,并且它不包含任何全局变量来解决未定义的外部符号,那么你有几个选择:
- 直接链接目标文件,而不是将其放入库中。(这是“标准”或“规范”的做法。) - 使用 DLL。尽管名称中带有“库”的字眼,但 DLL 不是库,而是目标文件,并以全有或全无的方式进行链接。 - 创建一个虚拟的全局符号,并在某处引用它。(这通常可以自动化完成,并且如果你作为第三方供应商提供库,则可能是首选解决方案。)

1

简短的回答是肯定的。强制注册的一种常见方法是执行以下操作:

static bool foo = register_type();

有没有一种方法可以强制链接器不忽略这些变量? - excray
3
在相关的翻译单元中,只需添加一些函数并调用该函数。这听起来可能像魔法,但标准要求在调用之前初始化静态变量,因此引入了依赖关系。祝好运! - Cheers and hth. - Alf
@Alf P. Steinbach,像def;这样的空使用是否足够?还是需要从中调用一个函数? - liaK
1
@liaK:C++98 §3.6.2/3 表示(在指出初始化是否在 main 的第一条语句之前完成是实现定义后):“如果将初始化推迟到 main 的第一条语句之后的某个时间点,则它应在与要初始化的对象在同一翻译单元中定义的任何函数或对象的第一次使用之前发生。” 因此,从标准上来说,您会处于安全地带。但我有一种直觉,即编译器可能会错误地优化掉对对象的空引用,因此我会使用一个函数。祝好运。 - Cheers and hth. - Alf
@Alf P. Steinbach,是的,没错。但我认为在这种情况下,仅仅为了使用而定义一个函数似乎有点奇怪。尽管如此,在我看来... :) - liaK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接