如果没有完全实现一个类,是否可以强迫共享的C ++库无法构建?

时间:2019-02-11 17:47:13

标签: c++ gcc dll cmake linker

我有C ++插件:

$reponse = array(
        'csrfName' => $this->security->get_csrf_token_name(),
        'csrfHash' => $this->security->get_csrf_hash()
        );
echo json_encode($reponse);

这是作为共享库实现的

class PluginBase
{
    public:

        virtual void foo () = 0;
        virtual void bar () = 0;
};

extern "C" PluginBase * new_instance ();

这是通过class PluginImplementation : public PluginBase { void foo () override; void bar () override; } void PluginImplementation::foo () {} // void PluginImplementation::bar () {} // NOTE: MISSING extern "C" PluginBase * new_instance () { return new PluginImplementation (); } 使用CMake构建的:

gcc

即使未实现ADD_LIBRARY (plugin_implementation SHARED PluginImplementation.cpp) ,也可以构建libplugin_implementation.so

我知道丢失的符号可能在运行时在程序的其他位置定义,因此链接器允许它从动态库中丢失。

我不要。

除非定义了所有 class 成员,否则是否有办法使PluginImplementation::bar无法构建?

2 个答案:

答案 0 :(得分:2)

我认为您将必须创建具有main的测试或其他代码,链接到共享库,并尝试实例化相关类。无论如何,这似乎是一个好主意,因为您应该进行单元测试。

答案 1 :(得分:2)

如果目标是现代ELF,并且您不希望通过其名称或其他符号直接引用此类,则可以将可见性设置为“隐藏”:

class __attribute__ ((visibility ("hidden")))
PluginImplementation : public PluginBase

然后,链接器将尝试在本地(在共享库中)解析用于实现虚拟方法的函数的符号,这将导致硬链接器错误(包装起来便于阅读):

plugin.o:(.data.rel.ro.local._ZTV20PluginImplementation
  [_ZTV20PluginImplementation]+0x18):
  undefined reference to `PluginImplementation::bar()'
/usr/bin/ld: plugin.so: hidden symbol `_ZN20PluginImplementation3barEv'
  isn't defined

即使您省略了控制vtable发出的成员函数(以便共享对象不包含带有函数指针的vtable),new_instance函数也会调用构造函数,该构造函数必须存储vtable指针,并且在隐藏可见性的情况下,也会产生未定义的符号错误。