添加结构体为何导致Android C++库(libMyLibrary.so)增大4KB?
问题分析与解决思路
核心原因
你遇到的4KB增量主要来自两个方面:
1. std::string初始化带来的附加代码
虽然你只定义了一个inline static字符串,但std::string是非POD类型,编译器需要生成:
- 字符串的全局构造函数:用来在程序启动时初始化
TestString,这段代码会被放入.text段; - 线程安全初始化的guard变量(就是你看到的
_ZGVN9Namespace5ITest10TestStringE):C++11及以后,全局静态变量的初始化是线程安全的,编译器会生成对应的检查和同步代码,同样占用.text空间。
而且因为你的结构体标记了EXPORT(可见性default),链接器会认为这些符号是外部模块可能依赖的,即使你的代码里没有直接调用,也不会被--gc-sections垃圾回收掉。
2. ELF段的页对齐填充
ELF文件的段大小默认是按**内存页大小(通常4KB)**对齐的。可能在添加结构体之前,你的.text段刚好接近一个页的边界,新增的少量代码触发了段的扩容,链接器会自动填充空字节到下一个页边界,导致看起来突然增加了4KB。从你提供的readelf输出看,.text段大小是0acb14,如果之前的大小是0abb14左右,刚好差一点到下一页,新增内容后就被对齐到了下一个4KB边界。
进一步排查方法
- 对比前后段信息:用
readelf -S分别导出添加结构体前后的so文件段信息,对比.text、.init_array等段的Size和Address,确认是否是对齐填充导致的增量。 - 反汇编查看新增代码:执行
objdump -d --demangle libMyLibrary.so,搜索和ITest::TestString相关的符号,找到对应的构造函数和同步代码,看看实际新增的代码量;同时检查是否有其他依赖的标准库函数(比如std::string的构造、析构相关函数)被意外引入。 - 验证可见性影响:临时把结构体的
EXPORT去掉(改成hidden可见性),重新编译链接,看so大小是否下降。如果变小,说明是default可见性导致相关代码无法被GC回收。 - 检查初始化条目:用
readelf -x .init_array libMyLibrary.so查看初始化数组,对比前后是否新增了std::string构造函数的条目,这些条目会关联到.text里的代码。
内容的提问来源于stack exchange,提问作者rstr1112
相关产品推荐
相关产品推荐

