[英]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.