Символ vtable может быть неопределенным, поскольку в классе отсутствует его ключевая функция

Я хочу отлаживать собственный исходный код Android, поэтому я меняю уровень оптимизации clang -Os -> -O0 ошибка:

frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h:171:error: undefined reference to 'vtable for android::HWComposer::HWCLayerInterface' prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/aarch64-linux-android/bin/ld.gold: the vtable symbol may be undefined because the class is missing its key function (see go/missingkeymethod) frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h:171: error: undefined reference to 'vtable for android::HWComposer::HWCLayerInterface' prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/aarch64-linux-android/bin/ld.gold: the vtable symbol may be undefined because the class is missing its key function (see go/missingkeymethod) frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h:171: error: undefined reference to 'vtable for android::HWComposer::HWCLayerInterface' prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/aarch64-linux-android/bin/ld.gold: the vtable symbol may be undefined because the class is missing its key function (see go/missingkeymethod) frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h:171: error: undefined reference to 'vtable for android::HWComposer::HWCLayerInterface' prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/aarch64-linux-android/bin/ld.gold: the vtable symbol may be undefined because the class is missing its key function (see go/missingkeymethod) out/target/product/rk3399_box/obj/SHARED_LIBRARIES/libsurfaceflinger_intermediates/DisplayHardware/HWComposer_hwc1.o:frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp:vtable for android::Iterable: error: undefined reference to 'android::HWComposer::HWCLayerInterface::setDataspace(android_dataspace)' out/target/product/rk3399_box/obj/SHARED_LIBRARIES/libsurfaceflinger_intermediates/DisplayHardware/HWComposer_hwc1.o:frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp:vtable for android::HWComposer::HWCLayer: error: undefined reference to 'android::HWComposer::HWCLayerInterface::setDataspace(android_dataspace)' clang++: error: linker command failed with exit code 1 (use -v to see invocation)

Я не хочу изменять исходный код Android, но хочу закрыть оптимизацию.

HWCLayerInterface:

    class HWCLayerInterface {
    protected:
        virtual ~HWCLayerInterface() { }
    public:
        virtual int32_t getCompositionType() const = 0;
        virtual uint32_t getHints() const = 0;
        virtual sp<Fence> getAndResetReleaseFence() = 0;
        virtual void setDefaultState() = 0;
        virtual void setSkip(bool skip) = 0;
        virtual void setIsCursorLayerHint(bool isCursor = true) = 0;
        virtual void setBlending(uint32_t blending) = 0;
        virtual void setTransform(uint32_t transform) = 0;
        virtual void setFrame(const Rect& frame) = 0;
        virtual void setCrop(const FloatRect& crop) = 0;
        virtual void setVisibleRegionScreen(const Region& reg) = 0;
        virtual void setSurfaceDamage(const Region& reg) = 0;
        virtual void setSidebandStream(const sp<NativeHandle>& stream) = 0;
        virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
        virtual void setAcquireFenceFd(int fenceFd) = 0;
        virtual void setPlaneAlpha(uint8_t alpha) = 0;
        virtual void onDisplayed() = 0;
        virtual void setDataspace(android_dataspace_t dataspace);
    };

HWCLayer:

    class HWCLayer : public HWCLayerInterface {
        friend class LayerListIterator;
        // select the layer at the given index
        virtual status_t setLayer(size_t index) = 0;
        virtual HWCLayer* dup() = 0;
        static HWCLayer* copy(HWCLayer *rhs) {
            return rhs ? rhs->dup() : NULL;
        }
    protected:
        virtual ~HWCLayer() { }
    };

Итерируемый:

    template<typename CONCRETE, typename HWCTYPE>
    class Iterable : public HWComposer::HWCLayer {
    protected:
        HWCTYPE* const mLayerList;
        HWCTYPE* mCurrentLayer;
        Iterable(HWCTYPE* layer) : mLayerList(layer), mCurrentLayer(layer),
                mIndex(0) { }
        inline HWCTYPE const * getLayer() const { return mCurrentLayer; }
        inline HWCTYPE* getLayer() { return mCurrentLayer; }
        virtual ~Iterable() { }
        size_t mIndex;
    private:
        // returns a copy of ourselves
        virtual HWComposer::HWCLayer* dup() {
            return new CONCRETE( static_cast<const CONCRETE&>(*this) );
        }
        virtual status_t setLayer(size_t index) {
            mIndex = index;
            mCurrentLayer = &mLayerList[index];
            return NO_ERROR;
        }
    };

HWCLayerVersion1:

    class HWCLayerVersion1 : public Iterable<HWCLayerVersion1, hwc_layer_1_t> {
        struct hwc_composer_device_1* mHwc;
    public:
    ......
        virtual void setDataspace(android_dataspace_t dataspace) {
            getLayer()->reserved[0] = dataspace & 0xFF;
            getLayer()->reserved[1] = (dataspace >> 8) & 0xFF;
            getLayer()->reserved[2] = (dataspace >> 16) & 0xFF;
            getLayer()->reserved[3] = (dataspace >> 24) & 0xFF;
        }
    }

Когда я меняю уровень оптимизации на -O2 или:

class HWCLayerInterface {
    protected:
        virtual ~HWCLayerInterface() { }
    public:
        virtual int32_t getCompositionType() const = 0;
        virtual uint32_t getHints() const = 0;
        virtual sp<Fence> getAndResetReleaseFence() = 0;
        virtual void setDefaultState() = 0;
        virtual void setSkip(bool skip) = 0;
        virtual void setIsCursorLayerHint(bool isCursor = true) = 0;
        virtual void setBlending(uint32_t blending) = 0;
        virtual void setTransform(uint32_t transform) = 0;
        virtual void setFrame(const Rect& frame) = 0;
        virtual void setCrop(const FloatRect& crop) = 0;
        virtual void setVisibleRegionScreen(const Region& reg) = 0;
        virtual void setSurfaceDamage(const Region& reg) = 0;
        virtual void setSidebandStream(const sp<NativeHandle>& stream) = 0;
        virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
        virtual void setAcquireFenceFd(int fenceFd) = 0;
        virtual void setPlaneAlpha(uint8_t alpha) = 0;
        virtual void onDisplayed() = 0;
        //change to default implemented
        virtual void setDataspace(android_dataspace_t dataspace) = 0;
    };

Этой ошибки не существует.

Пожалуйста, предоставьте минимальный воспроизводимый пример.

Passer By 24.12.2018 11:41
0
1
2 610
1

Ответы 1

= 0 не означает, что по умолчанию реализован, это означает, что он не реализован - вы оставляете за собой возможность вызывать setDataspace по указателям и ссылкам на HWCLayerInterface, но реализации HWCLayerInterface::setDataspace нет.

Если вы опустите = 0, вы обещаете, что где-то есть реализация HWCLayerInterface::setDataspace, и компоновщик будет ожидать, что она существует. Вы получаете ошибку, когда компоновщик сообщает вам, что вы обещали реализовать этот метод, но не предоставили его.

Уровень оптимизации не имеет значения, код C++ неверен, если вы объявляете метод, но не определяете его.

Так:

  • если вы хотите определить виртуальную функцию, которую дочерние элементы должен переопределяют, объявите ее как = 0;
  • если вы хотите определить виртуальную функцию, которую дочерние элементы мая переопределяют, но хотите, чтобы функция ничего не делала, если не переопределена, объявите ее пустой - например, virtual void setDataspace(android_dataspace_t dataspace) {}.

Для хорошего обслуживания вы должны пометить все, что вы отменяете, как override. Затем компилятор проверит, действительно ли вы что-то переопределили. Это защитит вас как от труднодоступных опечаток, так и от изменений в родительском классе, которые вы не можете отследить, и любое из них может превратить вашу попытку переопределения в некоторую автономную функцию. Также изучите final и выясните, когда это уместно применять к классу и / или замещаемой функции.

Другие вопросы по теме