使用-O3在GCC中共享库编译不会导出与-O0

时间:2018-05-17 22:03:41

标签: c++ linux templates gcc shared

我会征求您的意见。 我在gcc下遇到共享库编译问题。

有几个模板类和方法。使用-o0优化,每个都按预期导出,在-o3中,其中一些将被隐藏/不编译/不导出(nm输出清楚地显示它)。看起来这些方法是内联的,并且有一个错误。我看不出不同的原因。

问题:如何在-o3优化中导出所有符号。为什么-o0产生的不仅仅是-o3。

对于共享库中的模板,我可能需要一些特殊处理吗?例如,我应该进行明确的模板专业化?

如果需要,我将准备一个尽可能小的问题。

编辑:

git hub上的代码和详细的gcc日志(o0.log和o3.log):https://github.com/MOJNICK/shadow/tree/stack_debug/libcomparator

  

-O0中的nm输出(除了其他不值得一提的符号):

./lib/libcomparator.so:00000000000008e0 T instantiate()
./lib/libcomparator.so:000000000000098c W IterateProcess<unsigned char>::color_distance(unsigned char*, unsigned char*)
./lib/libcomparator.so:0000000000000950 W IterateProcess<unsigned char>::iterate_H(unsigned char*, unsigned char*)
./lib/libcomparator.so:0000000000000946 W IterateProcess<unsigned char>::IterateProcess()
./lib/libcomparator.so:0000000000000946 W IterateProcess<unsigned char>::IterateProcess()
./lib/libcomparator.so:0000000000000919 W std::pow(double, int)
     <-p> -O3中的nm输出(除了其他不值得一提的符号):   ./lib/libcomparator.so:00000000000006a0 T instantiate()

libcomparator.hpp

#ifndef COMPARATOR_HPP
    #define COMPARATOR_HPP
    #include <cmath>

    typedef char unsigned UCHAR;

    template <class TYPE>
    class IterateProcess
    {
    public:
        IterateProcess();
        double iterate_H(TYPE* pix0, TYPE* pix1);
        double color_distance(TYPE* pix0, TYPE* pix1);
    private:        
    };
#endif

libcomparator.cpp:

#include "libcomparator.hpp"

template <class TYPE> IterateProcess<TYPE>::IterateProcess(){}

template <class TYPE> double IterateProcess<TYPE>::iterate_H(TYPE* pix0, TYPE* pix1)
{
    return color_distance(pix0, pix1);
}

template <class TYPE> double IterateProcess<TYPE>::color_distance(TYPE* pix0, TYPE* pix1)
{
    double var = -(pix1[0] / static_cast<double>(pix0[0]) + pix1[1] / static_cast<double>(pix0[1]) + pix1[2] / static_cast<double>(pix0[2]));//for minimize color_distance
    return std::pow(pix1[0] / static_cast<double>(pix0[0]) + var, 2) + std::pow(pix1[1] / static_cast<double>(pix0[1]) + var, 2) + std::pow(pix1[2] / static_cast<double>(pix0[2]) + var, 2);
}

void instantiate()
{
    UCHAR pix [] = {10,10,10};
    IterateProcess<UCHAR> specifyIT;
    specifyIT.iterate_H(pix, pix);
}

如果您需要构建,请执行Release。 要在主CmakeLists.txt中将-O3切换到-O0注释掉行:

string( REPLACE "-O3" "-O0" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})

1 个答案:

答案 0 :(得分:2)

你必须告诉编译器它应该总是导出符号,即使它们可以在优化的情况下被删除,如:

 template class __attribute__((visibility ("default"))) IterateProcess<UCHAR>;

在课程定义后添加此项,您应该输出符号。

添加后我得到了:

0000000000000910 W _ZN14IterateProcessIhE14color_distanceEPhS1_
0000000000000880 W _ZN14IterateProcessIhE9iterate_HEPhS1_
0000000000000870 W _ZN14IterateProcessIhEC1Ev
0000000000000870 W _ZN14IterateProcessIhEC2Ev

我编译:

 g++ -shared main.cpp -O3 -o x.so -fPIC

编辑:为什么默认情况下看不到优化代码:

只是因为它没有生成!如果来自instantiate的来电完全内联,则任何目标文件中都不会留下任何代码,因为它永远不再需要了。要创建共享库,您必须告诉编译器您确实想要获取当前未使用的实例。但这是一个非常模糊的用例!在c ++中,您应该尽可能在头文件中出现,以使编译器尽可能地进行优化!因此,在.h / .cpp中拆分代码并将模板代码放入cpp文件中我很少建议你避免这种情况。