You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

添加-fvisibility=hidden后,普通成员函数编译失败虚函数正常?

为什么添加-fvisibility=hidden后,普通成员函数链接失败而虚函数正常?

当编译动态库librectangle.so时使用-fvisibility=hidden全局隐藏所有符号,仅将get_rectangle()函数通过__attribute__((visibility("default")))导出,编写main.cpp链接该动态库时,调用普通成员函数会出现链接错误,但将成员函数改为虚函数后可正常编译运行,原因如下:


1. 普通成员函数链接失败的核心原因

普通成员函数采用静态绑定机制:

  • 编译main.cpp时,编译器会直接生成对Rectangle::set_values(int, int)和Rectangle::area()的符号引用——因为代码中是通过对象指针直接调用成员函数,编译器在编译期就确定了要调用的函数符号。
  • 由于-fvisibility=hidden的全局设置,未显式标记为visibility("default")的普通成员函数符号会被默认隐藏,动态库librectangle.so中不会导出这些符号。
  • 链接阶段,链接器在动态库中找不到对应的导出符号,因此抛出undefined reference错误。
  • 用nm -C librectangle.so查看符号时,普通成员函数的符号类型为t(本地符号,仅在库内部可见),而非导出的T类型。

普通成员函数版本代码示例

rectangle.h

#pragma once

#include <memory>

class Rectangle {
    int width, height;
  public:
    void set_values (int,int);
    int area();

};

std::shared_ptr<Rectangle> __attribute__((visibility("default"))) get_rectangle();

rectangle.cpp

#include "rectangle.h"

int Rectangle::area() {return width*height;}

void Rectangle::set_values (int x, int y) {
  width = x;
  height = y;
}

std::shared_ptr<Rectangle> __attribute__((visibility("default"))) get_rectangle() {
    return std::make_shared<Rectangle>();
}

main.cpp

#include "../rectangle/rectangle.h"

int main() {
    auto rectangle = get_rectangle();
    rectangle->set_values(2, 3);
    rectangle->area();
    return 0;
}

链接错误信息

undefined reference to `Rectangle::set_values(int, int)'
undefined reference to `Rectangle::area()'

2. 虚函数能正常工作的核心原因

虚函数采用动态绑定机制:

  • 当类包含虚函数时,编译器会为该类生成虚表(vtable),每个类实例会携带一个指向虚表的指针。调用虚函数时,程序会通过对象的虚表指针找到虚表,再从虚表中获取函数地址进行调用,这个过程是在运行时完成的。
  • 由于get_rectangle()是导出的函数,且在动态库内部创建了Rectangle的实例,虚表的符号会被隐式包含在导出的依赖中(虚表与实例绑定,实例通过导出函数返回,因此虚表会被标记为可被外部访问)。
  • 编译main.cpp时,编译器不会直接生成对Rectangle::set_values或Rectangle::area()的符号引用,而是生成通过虚表间接调用的代码,因此链接阶段不需要依赖这些成员函数的导出符号,自然不会出现链接错误。
  • 用nm -C librectangle.so查看符号时,会看到vtable for Rectangle是导出的T类型符号,而虚函数的实现符号虽为本地t类型,但不影响外部调用。

虚函数版本代码示例(修改后的rectangle.h)

#pragma once

#include <memory>

class Rectangle {
    int width, height;
  public:
    virtual void set_values (int,int);
    virtual int area();

};

std::shared_ptr<Rectangle> __attribute__((visibility("default"))) get_rectangle();

内容的提问来源于stack exchange,提问作者quanquanquan97

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 02:58:27