如何防止编译出“未使用的”全局变量?

时间:2009-08-04 19:26:50

标签: c++ global-variables

我正在使用静态初始化来简化在C ++中使用工厂注册某些类的过程。不幸的是,我认为编译器正在优化“未使用的”对象,这些对象旨在在其构造函数中执行有用的工作。有没有办法告诉编译器不要优化全局变量?

class SomeClass {
    public:
        SomeClass() {
            /* do something useful */
        }
};

SomeClass instance;

我在SomeClass的构造函数中的断点没有被击中。在我的实际代码中,SomeClass位于头文件中,实例位于源文件中,或多或少是单独的。

编辑:正如KJAWolf猜测的那样,这段代码实际上被编译成静态库,而不是可执行文件。它的目的是注册静态库提供的一些类型,静态列表类型及其创建者,然后工厂从构造中读取。由于这些类型随lib一起提供,因此不希望将此代码添加到可执行文件中。

此外,我发现通过将代码移动到包含其他现有代码的另一个源文件,它可以正常工作。似乎拥有一个纯粹由这些全局对象组成的文件是导致问题的原因。就好像翻译单元完全被忽略了一样。

9 个答案:

答案 0 :(得分:37)

不允许编译器优化全局对象 即使他们从未使用过。

您的代码中还发生了其他事情 现在,如果您使用全局对象构建了一个静态库,并且未从可执行文件中引用该全局对象,则链接器不会将其拉入可执行文件。

答案 1 :(得分:5)

编译器永远不应该优化掉这样的全局变量 - 如果它这样做,它就会被打破。

答案 2 :(得分:2)

为了构建Arthur Ulfeldt,volatile告诉编译器这个变量可以在编译器知识之外进行更改。我用它来放置一个语句,允许调试器设置断点。它对于可以根据环境或需要特殊序列进行更改的硬件寄存器也很有用。即串行端口接收寄存器和某些看门狗寄存器。

答案 3 :(得分:1)

你可以使用

#pragma optimize off
int globalVar
#pragma optimize on

但我不知道如果它只适用于Visual Studio(http://msdn.microsoft.com/en-us/library/chh3fb0k(VS.80).aspx)。

你也可以告诉编译器根本不进行优化,特别是如果你正在调试......

答案 4 :(得分:1)

在构建完整的静态库之前,你可以强制一个对象(你的类型列表)通过部分链接来拉动其他对象。

使用GNU linker

ld -Ur -o TypeBundle.o type1.o type2.o type3.o static_list.o
ld -static -o MyStaticLib.a type_bundle.o other_object.o another_object.o ...

因此,只要代码使用库引用静态列表,完整的“TypeBundle.o”对象就会链接到生成的二进制文件中,包括type1.o,type2.o和type3.o。

在此期间,请查看the manual中“-Ur”的含义。

答案 5 :(得分:0)

您使用gcc与gdb?过去有一个问题,gdb无法在构造函数中准确设置断点。

另外,您使用的是优化级别,它允许编译器在类定义中内联方法。

答案 6 :(得分:0)

我有相同的设置& VS2008上的问题。 我发现,如果您宣布上课dllexport,则不会优化。

class __declspec( dllexport ) Cxxx
{
.
}

然而,这会在我的情况下产生很多警告,因为我必须将此类中使用的所有类也声明为dllexport。

所有优化都处于关闭状态(在调试模式下),这仍然是优化的。 volatile / pragma也优化了。在这个类创建的全局变量(在相同的cpp文件中)等不起作用。

刚刚发现dllexport至少需要在exe的其他一些cpp文件中包含这些类的头文件才能工作!因此,只有选项是为每个类添加一个调用某些静态成员的文件,并将此文件添加到使用这些类的所有项目中。

答案 7 :(得分:0)

链接时需要使用-whole-archive。请参阅答案:

ld linker question: the --whole-archive option

答案 8 :(得分:-2)

如何使用关键字volatile?它会阻止编译器进行太多优化。