代码之家  ›  专栏  ›  技术社区  ›  Ben Hymers

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

  •  21
  • Ben Hymers  · 技术社区  · 15 年前

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

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

    我在someclass的构造函数中的断点不会被击中。在我的实际代码中,someclass在头文件中,而instance在源文件中,或多或少是单独的。

    编辑:正如kjawolf所猜测的,这段代码实际上是编译成一个静态lib,而不是可执行的。它的目的是用静态类型列表及其创建者注册静态lib提供的一些类型,以便工厂在构建时读取这些类型。由于这些类型与lib一起提供,因此不希望将此代码添加到可执行文件中。

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

    9 回复  |  直到 8 年前
        1
  •  37
  •   Loki Astari    15 年前

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

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

        2
  •  5
  •   Pavel Minaev    15 年前

    编译器永远不应该优化掉这样的全局——如果它这样做了,它就完全被破坏了。

        3
  •  2
  •   Robert Deml    15 年前

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

        4
  •  1
  •   atk    15 年前

    你可以使用

    #pragma optimize off
    int globalVar
    #pragma optimize on
    

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

    您还可以告诉编译器不要进行任何优化,尤其是在调试时…

        5
  •  1
  •   gatopeich    8 年前

    您可以强制一个对象(您的类型列表)通过 部分链接 在构建完整的静态lib之前。

    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。

    在那里,一定要看看“-ur”的意思。 the manual .

        6
  •  0
  •   Juan    15 年前

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

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

        7
  •  0
  •   Community uzul    7 年前

    链接时需要使用整个存档。请参阅以下答案:

    ld linker question: the --whole-archive option

        8
  •  0
  •   Peter O. Manuel Pinto    12 年前

    我在VS2008上有相同的设置问题。 我发现如果你宣布你和 dllexport 它不会优化。

    class __declspec( dllexport ) Cxxx
    {
    .
    }
    

    但是,在我的例子中,这会产生很多警告,因为我必须将此类中使用的所有类也声明为dllexport。

    所有优化都已关闭(在调试模式下),但这仍然是优化的。同时关闭volatile/pragma optimize。在这个类(在同一个cpp文件中)等创建的全局变量上不起作用。

    刚刚发现dllexport至少需要将这些类的头文件包含在一些其他cpp文件中,从exe开始工作!所以唯一的选择是为每个类添加一个带有对某些静态成员调用的文件,并将这个文件添加到所有使用这些类的项目中。

        9
  •  -2
  •   Partial    15 年前

    使用关键字volatile怎么样?它将防止编译器进行过多的优化。