我有一个我在Android中使用的库,但我确定这个问题并非特定于Android。 这个库包含一系列打印到logcat的错误代码,并且它们全部由一个常量字符串组成。库中的`const char *`存储的奇怪行为.so文件
...
if(...){ALOGE("Error in parameter XXXXXX");}
if(...){ALOGE("Error in parameter YYYYYY");}
if(...){ALOGE("Error in parameter ZZZZZZ");}
...
今天我注意到我的.rodata节(大约16kB)有大量的数据。所以我运行了一个strings mylib.so
,我收到了一堆字符串。
Error in parameter XXXXXX
Error in parameter YYYYYY
Error in parameter ZZZZZZ
我虽然,与印刷的一个小的额外费用(这应该是很好的,因为这些代码很少使用),我可以节省大量的空间,如果我在第2个部分拆分字符串。然后编译器应该完成这个工作,并且将一个字符串中的公共部分分组。由于编译器具有重复的字符串移除优化步骤(CLANG和GCC)。
我就是这么做的:(我有很多这样的,但他们都有这样的模式,我知道我应该使用一个定义(但这是一个快速测试))
...
if(...){ALOGE("Error in parameter %s","XXXXXX");}
if(...){ALOGE("Error in parameter %s","YYYYYY");}
if(...){ALOGE("Error in parameter %s","ZZZZZZ");}
...
什么我发现是这样的:
- 该库是完全相同的大小。
.rodata
现在小得多,但.text
增加了几乎相同的数额。 (只有几个字节的差别) strings
命令现在打印1次只有"Error in parameter %s"
字符串,和分离的部分。所以没有字符串合并发生。- 似乎没有,如果我在32位,64位等编译到重要..
那么,究竟是怎么回事?我该如何解决?任何指导?编译器在做什么? 由于
额外数据:
- 编译CLANG 4.9(4.8确实相同的结果)。
- 标志:-Os -fexceptions -std = C++ 11 -fvisivility =隐藏
编辑:
我使用GCC相同的结果Online GCC
创建了一个在线示例性测试拆分:
#include <stdio.h>
int main()
{
int a = rand()%7;
switch(a){
case 0: printf("Hello, %s!\n","Anna"); break;
case 1: printf("Hello, %s!\n","Bob"); break;
case 2: printf("Hello, %s!\n","Clark"); break;
case 3: printf("Hello, %s!\n","Danniel"); break;
case 4: printf("Hello, %s!\n","Edison"); break;
case 5: printf("Hello, %s!\n","Foo"); break;
case 6: printf("Hello, %s!\n","Garret"); break;
}
return 0;
}
NonSp点亮:
#include <stdio.h>
int main()
{
int a = rand()%7;
switch(a){
case 0: printf("Hello, Anna!\n"); break;
case 1: printf("Hello, Bob!\n"); break;
case 2: printf("Hello, Clark!\n"); break;
case 3: printf("Hello, Danniel!\n"); break;
case 4: printf("Hello, Edison!\n"); break;
case 5: printf("Hello, Foo!\n"); break;
case 6: printf("Hello, Garret!\n"); break;
}
return 0;
}
编译时:
gcc -Os -o main main.c
gcc -Os -o main2 main2.c
尺寸:
-rwxr-xr-x 1 20446 20446 8560 Nov 16 11:43 main
-rw-r--r-- 1 20446 20446 478 Nov 16 11:41 main.c
-rwxr-xr-x 1 20446 20446 8560 Nov 16 11:42 main2
-rw-r--r-- 1 20446 20446 443 Nov 16 11:39 main2.c
字符串:
strings main2 | grep "Hello"
Hello, Anna!
Hello, Bob!
Hello, Clark!
Hello, Danniel!
Hello, Edison!
Hello, Foo!
Hello, Garret!
strings main | grep "Hello"
Hello, %s!
'.text'用于代码 – Danh
您使用什么编译器?这是C代码还是C++代码?你使用了哪些优化设置? –
这是C++,标志没有什么特别的。只是-Os。如果我没有记错,编译器是叮当声4.9(ndk r13b) – DarkZeros