简体   繁体   English

GCC中带有-O3的共享库编译不会导出与-O0中一样多的符号

[英]Shared library compilation in GCC with -O3 don't export as much symbols as in -O0

I would ask for your advice. 我会问你的建议。 I have a problem with shared library compilation under gcc. 我在gcc下共享库编译有问题。

There are several template class and methods. 有几种模板类和方法。 With -o0 optimization each one is exported as expected, in -o3 some of them will be hidden/not compiled/not exported (nm output clearly shows it). 通过-o0优化,每个文件都按预期导出,在-o3中,其中一些将被隐藏/不编译/不导出(nm输出清楚地显示了它)。 It looks like the methods are getting inline and there is a bug with it. 看来这些方法已内联,并且存在错误。 I cannot see different reason. 我看不出其他原因。

The question: How to export all symbols in -o3 optimization. 问题:如何在-o3优化中导出所有符号。 Why -o0 produce more than -o3. 为什么-o0产生比-o3更多的东西。

Maybe I need some special treatment in case of templates in shared library? 如果共享库中的模板可能需要特殊处理? For example I should make explicit template specialization? 例如,我应该使显式模板专业化吗?

If needed, I will prepare a smallest possible example with the issue. 如果需要,我将为这个问题准备一个最小的示例。

edit: 编辑:

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

nm output in -O0 (among other not worth to mention symbols): -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) 

nm output in -O3 (among other not worth to mention symbols): ./lib/libcomparator.so:00000000000006a0 T instantiate() -O3中的nm输出(除其他不值得提及的符号外): ./lib/libcomparator.so:00000000000006a0 T instantiate() : ./lib/libcomparator.so:00000000000006a0 T instantiate()

libcomparator.hpp 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: 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);
}

If you need to build, do in Release. 如果需要构建,请在Release中进行。 To switch -O3 to -O0 comment out line in main CmakeLists.txt: 要将-O3切换为-O0,请在主CmakeLists.txt中注释掉以下行:

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

You have to tell the compiler that it should always export the symbols even if they could be removed in case of optimization like: 您必须告诉编译器,即使在优化的情况下可以删除符号,也应始终导出符号:

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

Add this after your class definition and you should get the symbols exported. 在类定义之后添加此符号,您应该导出符号。

After adding this I got: 添加后,我得到:

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

I compiled with: 我编译了:

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

EDIT: Why optimized code is not seen by default: 编辑:为什么默认情况下看不到优化的代码:

Simply because it is not generated! 只是因为它不是生成的! If your call from instantiate is fully inlined, there is no code left in any object file because it is never needed anymore. 如果您从instantiate调用完全内联,则在任何目标文件中都不会留下任何代码,因为不再需要它。 For creating a shared library, you have to tell the compiler, that you really want to get currently unused instances. 为了创建共享库,您必须告诉编译器您确实要获取当前未使用的实例。 But this is a really obscure use case! 但这是一个非常晦涩的用例! In c++ you should present most as possible in header files to enable the compiler to optimize as much as possible! 在c ++中,应尽可能在头文件中显示,以使编译器尽可能优化! So splitting code in .h/.cpp and place template code into cpp file is really seldom I would advice you to avoid that. 因此,实际上很少建议将.h / .cpp中的代码拆分并将模板代码放入cpp文件中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM