我有一個我在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