首页 > 解决方案 > 目标文件在 Linux 上比在 macOS 或 Windows 上大 2.5 倍

问题描述

我有一个文件,当编译为目标文件时,它具有以下大小:

该文件(下文详述)是 Unicode 表(的一部分)以及字符属性的表示。编码为utf8。

我突然想到问题可能是 libstdc++ 不能很好地处理文件,所以我在 Gentoo 上用 clang 尝试了 libc++,但它没有做任何事情(目标文件大小保持不变)。

然后我认为可能是一些优化做了一些奇怪的事情,但是当我从-O3-O0.

该文件第 50 行包括UnicodeTable.inc. UnicodeTable.inc包含一个unicodestd::array代码点。

我尝试更改std::array为 C 样式数组,但同样,目标文件大小没有改变。

我有CodePoint.cpp可以编译的预处理版本$CC -xc++ CodePoint.i -c -o CodePoint.oCodePoint.i包含大约 40k 行 STL 代码和大约 130k 行 unicode 表。

我尝试将预处理后的内容上传CodePoint.i到 gists.github.com 和 paste.pound-python.org,但都拒绝了 170k 行长文件。

在这一点上,我没有想法,非常感谢有关找出“臃肿”目标文件大小来源的任何帮助。

标签: c++linuxwindowsmacos

解决方案


从您链接的输出中,您可以看到 elf 对象(部分)size中有 12 MB 的重定位。.rela.dyn如果64 位重定位需要 24 个字节,并且您有 132624 个表条目,每个条目有 4 个指向字符串的指针,这几乎可以解释 12 MB 的差异(132624 *4 * 24 = 12731904 ~ 12 MB)。

显然,其他格式要么使用更有效的重定位类型,要么直接链接引用,并将整个块与字符串一起重定位为一块内存。

由于您将此链接到共享库,因此动态重定位不会消失。

我不确定您当前使用的代码是否可以避免这种情况。但是,我认为 unicode 代码点必须具有最大大小。为什么不将代码点按值存储在 RawCodePoint 结构中的 char 数组中?每个代码点字符串的大小不应大于您当前存储的指针,并且查找表的引用位置实际上可能会有所改善。

constexpr size_t MAX_CP_SIZE = 4; // Check if that is correct

struct RawCodePointLocal {
  const std::array<char, MAX_CP_SIZE> original;
  const std::array<char, MAX_CP_SIZE> normal;
  const std::array<char, MAX_CP_SIZE> folded_case;
  const std::array<char, MAX_CP_SIZE> swapped_case;
  bool is_letter;
  bool is_punctuation;
  bool is_uppercase;
  uint8_t break_property;
  uint8_t combining_class;
};

这样,您不需要对条目进行重定位。


推荐阅读