简体   繁体   中英

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.

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). 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. Why -o0 produce more than -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

nm output in -O0 (among other not worth to mention symbols):

 ./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()

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);
}

If you need to build, do in Release. To switch -O3 to -O0 comment out line in main 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. 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! So splitting code in .h/.cpp and place template code into cpp file is really seldom I would advice you to avoid that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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