簡體   English   中英

GCC中帶有-O3的共享庫編譯不會導出與-O0中一樣多的符號

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

我會問你的建議。 我在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) 

-O3中的nm輸出(除其他不值得提及的符號外): ./lib/libcomparator.so:00000000000006a0 T instantiate() : ./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中進行。 要將-O3切換為-O0,請在主CmakeLists.txt中注釋掉以下行:

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

您必須告訴編譯器,即使在優化的情況下可以刪除符號,也應始終導出符號:

 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文件中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM