Компиляция совместно используемой библиотеки в GCC с -O3 не экспортирует столько символов, сколько в -O0 - PullRequest
0 голосов
/ 18 мая 2018

Я бы попросил вашего совета.У меня проблема с компиляцией разделяемой библиотеки в gcc.

Существует несколько шаблонных классов и методов.При оптимизации -o0 каждый экспортируется, как и ожидалось, в -o3 некоторые из них будут скрыты / не скомпилированы / не экспортированы (отчет об этом ясно показывает вывод в нм).Похоже, что методы становятся встроенными, и в этом есть ошибка.Я не вижу другой причины.

Вопрос: Как экспортировать все символы в оптимизации -o3.Почему -o0 производит больше, чем -o3.

Может быть, мне нужна особая обработка в случае шаблонов в общей библиотеке?Например, я должен сделать явную специализацию шаблона?

При необходимости я подготовлю наименьший возможный пример с этой проблемой.

edit:

Код и подробные журналы gcc (o0.log и o3.log) на git hub: https://github.com/MOJNICK/shadow/tree/stack_debug/libcomparator

nm вывод в -O0 (среди прочих не стоит упоминать символы):

./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 (среди прочих не стоит упоминать символы): ./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})

1 Ответ

0 голосов
/ 18 мая 2018

Вы должны указать компилятору, что он всегда должен экспортировать символы, даже если они могут быть удалены в случае оптимизации, например:

 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 очень редко, я бы посоветовал вам этого избежать.

...