字符串文字的编译输出中.rodata和.rodata.str1.4部分有什么区别?

meh*_*zer 6 c compilation

例如,当我有:

const char mesg [] = "Hello World";
Run Code Online (Sandbox Code Playgroud)

它是直接放入,.rodata但当我有:

const char* mesg = "Hello World";
Run Code Online (Sandbox Code Playgroud)

它被直接放入 .rodata.str1.4

当我们使用指针时,它们和我们使用.rodata.str1.4的原因有什么区别?

Art*_*Art 5

我做了几个实验,看起来编译器将字符串放置在目标文件的特殊部分中。有趣的事情发生在编译二进制文件时,字符串按预期以 .rodata 结尾。进一步的实验表明,如果不同的对象中有相同的字符串,它们会在生成的二进制文件中统一为相同的字符串。

所以我怀疑这样做的原因是编译器想要给链接器提供一些关于只读数据的信息,而不是“它是只读的”,以便最终的链接可以就如何处理它做出更明智的决定,包括重复数据删除。

$ 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..
[...]
Run Code Online (Sandbox Code Playgroud)