代码之家  ›  专栏  ›  技术社区  ›  spraff

如果一个类没有完全实现,我能强制共享C++库失败吗?

  •  0
  • spraff  · 技术社区  · 6 年前

    我有C++插件:

    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 尽管 PluginImplementation::bar 未实现。

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

    我不想那样。

    有没有办法 .so 除非全部 是否定义了成员?

    2 回复  |  直到 6 年前
        1
  •  2
  •   Florian Weimer    6 年前

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

    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指针的构造函数,在隐藏可见性的情况下,也会产生未定义的符号错误。

        2
  •  2
  •   Omnifarious    6 年前

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