zrobiłem kilka eksperymentów, wygląda na to kompilator umieszcza w specjalnych sekcjach ciągi w plikach obiektowych. Ciekawa rzecz dzieje się podczas kompilacji pliku binarnego, łańcuchy kończą się w .rodata zgodnie z oczekiwaniami. Dalsze eksperymenty pokazują, że to, co się dzieje, polega na tym, że jeśli masz ten sam ciąg znaków w różnych obiektach, stają się one ujednolicone w tym samym łańcuchu w wynikowym pliku binarnym.
Podejrzewam, że powodem jest to, że kompilator chce przekazać linkerowi informacje o danych tylko do odczytu innych niż "jest tylko do odczytu", aby ostateczny link mógł podejmować bardziej inteligentne decyzje jak sobie z tym poradzić, w tym deduplikacji.
$ cat foo.c
const char *
fun(int i)
{
const char *foo = "foofoo foo foo foo";
const char *bar = "barbar bar bar bar";
return i ? foo : bar;
}
$ cat bar.c
#include <stdio.h>
extern const char *fun(int);
int
main(int argc, char **argv)
{
const char *foo = "foofoo foo foo foo";
printf("%s%s\n", foo, fun(1));
return 0;
}
$ cc -c -O2 foo.c
$ cc -c -O2 bar.c
$ objdump -s foo.o
[...]
Contents of section .rodata.str1.1:
0000 62617262 61722062 61722062 61722062 barbar bar bar b
0010 61720066 6f6f666f 6f20666f 6f20666f ar.foofoo foo fo
0020 6f20666f 6f00 o foo.
[...]
$ objdump -s bar.o
[...]
Contents of section .rodata.str1.1:
0000 666f6f66 6f6f2066 6f6f2066 6f6f2066 foofoo foo foo f
0010 6f6f0025 7325730a 00 oo.%s%s..
[...]
$ cc -o foobar foo.o bar.o
$ objdump -s foobar
[...]
Contents of section .rodata:
400608 01000200 00000000 00000000 00000000 ................
400618 62617262 61722062 61722062 61722062 barbar bar bar b
400628 61720066 6f6f666f 6f20666f 6f20666f ar.foofoo foo fo
400638 6f20666f 6f002573 25730a00 o foo.%s%s..
[...]
Jakie polecenie kompilatora, wersji i kompilacji? –
clang 3.5 umieszcza oba na '.rodata.str1.1' dla lokalnych literałów ciągowych,' .data' dla globali, więc nie odtwarzam ich w pełni. –