我有一个相当简单的C ++项目,它使用boost :: regex库。我得到的输出是3.5Mb。据我所知,我静态链接所有boost .CPP文件,包括所有函数/方法。也许有可能以某种方式指示我的链接器只使用boost中的必要元素,而不是所有元素?感谢。
$ c++ —version
i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5659)
这是size
所说的:
$ size a.out
__TEXT __DATA __OBJC others dec hex
1556480 69632 0 4296504912 4298131024 100304650
我尝试了strip
:
$ ls -al
... 3946688 May 21 13:20 a.out
$ strip a.out
$ ls -al
... 3847248 May 21 13:20 a.out
PS。这就是我的代码组织方式(也许这是问题的主要原因):
// file MyClass.h
class MyClass {
void f();
};
#include "MyClassImpl.h"
// file MyClassImpl.h
void MyClass::f() {
// implementation...
}
// file main.cpp
#include "MyClass.h"
int main(int ac, char** av) {
MyClass c;
c.f();
}
您怎么看?
答案 0 :(得分:16)
您是否在启用调试符号的情况下编译?这可能占大小的很大一部分。另外你如何确定二进制文件的大小?假设您使用的是类似UNIX的平台,可以使用直接的“ls -l
”或“size
”命令。如果二进制包含调试符号,则两者可能会产生截然不同的结果。例如,以下是构建Boost.Regex“credit_card_example.cpp”示例时获得的结果。
$ g++ -g -O3 foo.cpp -lboost_regex-mt
$ ls -l a.out
-rwxr-xr-x 1 void void 483801 2010-05-20 10:36 a.out
$ size a.out
text data bss dec hex filename
73330 492 336 74158 121ae a.out
仅生成目标文件时会出现类似的结果:
$ g++ -c -g -O3 foo.cpp
$ ls -l foo.o
-rw-r--r-- 1 void void 622476 2010-05-20 10:40 foo.o
$ size foo.o
text data bss dec hex filename
49119 4 40 49163 c00b foo.o
编辑:添加了一些静态链接结果......
这是静态链接时的二进制大小。它更接近你得到的东西:
$ g++ -static -g -O3 foo.cpp -lboost_regex-mt -lpthread
$ ls -l a.out
-rwxr-xr-x 1 void void 2019905 2010-05-20 11:16 a.out
$ size a.out
text data bss dec hex filename
1204517 5184 41976 1251677 13195d a.out
大部分大尺寸也可能来自Boost.Regex库所依赖的其他库。在我的Ubuntu框中,Boost.Regex共享库的依赖项如下:
$ ldd /usr/lib/libboost_regex-mt.so.1.38.0
linux-gate.so.1 => (0x0053f000)
libicudata.so.40 => /usr/lib/libicudata.so.40 (0xb6a38000)
libicui18n.so.40 => /usr/lib/libicui18n.so.40 (0x009e0000)
libicuuc.so.40 => /usr/lib/libicuuc.so.40 (0x00672000)
librt.so.1 => /lib/tls/i686/cmov/librt.so.1 (0x001e2000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x001eb000)
libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0x00110000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x009be000)
libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0x00153000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x002dd000)
/lib/ld-linux.so.2 (0x00e56000)
ICU库可能变得非常大。除了调试符号外,它们可能是二进制文件大小的主要贡献者。此外,在静态链接的情况下,看起来Boost.Regex库本身由大对象文件组成:
$ size --totals /usr/lib/libboost_regex-mt.a | sort -n
0 0 0 0 0 regex_debug.o (ex /usr/lib/libboost_regex-mt.a)
0 0 0 0 0 usinstances.o (ex /usr/lib/libboost_regex-mt.a)
0 0 0 0 0 w32_regex_traits.o (ex /usr/lib/libboost_regex-mt.a)
text data bss dec hex filename
435 0 0 435 1b3 regex_raw_buffer.o (ex /usr/lib/libboost_regex-mt.a)
480 0 0 480 1e0 static_mutex.o (ex /usr/lib/libboost_regex-mt.a)
1543 0 36 1579 62b cpp_regex_traits.o (ex /usr/lib/libboost_regex-mt.a)
3171 632 0 3803 edb regex_traits_defaults.o (ex /usr/lib/libboost_regex-mt.a)
5339 8 13 5360 14f0 c_regex_traits.o (ex /usr/lib/libboost_regex-mt.a)
5650 8 16 5674 162a wc_regex_traits.o (ex /usr/lib/libboost_regex-mt.a)
9075 4 32 9111 2397 regex.o (ex /usr/lib/libboost_regex-mt.a)
17052 8 4 17064 42a8 fileiter.o (ex /usr/lib/libboost_regex-mt.a)
61265 0 0 61265 ef51 wide_posix_api.o (ex /usr/lib/libboost_regex-mt.a)
61787 0 0 61787 f15b posix_api.o (ex /usr/lib/libboost_regex-mt.a)
80811 8 0 80819 13bb3 icu.o (ex /usr/lib/libboost_regex-mt.a)
116489 8 112 116609 1c781 instances.o (ex /usr/lib/libboost_regex-mt.a)
117874 8 112 117994 1ccea winstances.o (ex /usr/lib/libboost_regex-mt.a)
131104 0 0 131104 20020 cregex.o (ex /usr/lib/libboost_regex-mt.a)
612075 684 325 613084 95adc (TOTALS)
如果部分或全部目标文件链接到您的二进制文件中,您可以单独使用Boost.Regex来获得~600K。
答案 1 :(得分:6)
-O3
标志不会优化代码的大小,而是优化执行速度。也许例如一些循环展开将导致更大的文件。尝试使用其他一些优化标志进行编译。 -Os
标志将针对小型可执行文件进行优化。
答案 2 :(得分:2)
如果您是静态链接,那么大多数链接器将只包含所需的对象。
3.5Mb并不是那么大 - 在PC系统上,所以尺寸可能取决于操作系统等
答案 3 :(得分:1)
如果您正确设置了链接顺序(最依赖,最少依赖),链接器应该只抓取程序实际使用的符号。此外,由于模板使用,很多(但不是全部,我不能说正则表达式)提升功能仅限于标题。
更有可能的是,调试信息/符号表/等会占用二进制文件中的空间。模板名称(例如iostream和标准容器)非常长,并在符号表中创建大型条目。
你没有说你正在使用什么操作系统,但如果它是一个unix变种作为测试,你实际上strip
你的二进制文件的副本可以删除所有额外的信息,看看还剩下什么:
cp a.out a.out.test
strip a.out.test
ls -l a.out*
在我测试的一个二进制文件上,它删除了大约90%的文件大小。请注意,如果你这样做,任何内核都没有用于调试的未经剥离的二进制文件的副本 - 你将没有任何符号名称或任何东西,只是汇编和地址。 3.5 MB在现代真的是一个小文件。即使只有10Ksloc的源,也很可能只有很多调试/符号信息。
答案 4 :(得分:1)
你说你有3个文件。 对我来说,MyClassImpl.h可能是一个.cpp,因为它包含实现。
无论如何,如果你实际上正在编译两个文件,包括boost :: regex,你最终会得到两倍于boost :: regex的大小(正是如果你在两个文件中使用相同的功能,你将有两倍的成本)在太空中。)
这是因为大多数提升功能都是内联模板。
最好的,
答案 5 :(得分:0)
如果你有ldd可用,你可以用它来检查你是否真的链接到所有的boost库。
另一种可能性是大小是使用头文件库的副作用,许多增强库都是那种类型,包括它们可以内联更多你可以相信的代码。由于使用了几种不同的模板参数,您还可以产生某种组合爆炸。
要获得更好的诊断,您应该尝试使用正则表达式创建一个非常短的程序,并查看您获得的大小。如果你的程序真的很短3.5 Mo很大。我当前的projet可执行文件也使用BOOST(但不是正则表达式)并且大小相同。但我说的是大约20000行C ++。因此,某处应该有一个捕获。