c++ - 与 GCC 共享不一致的字符串文字

标签 c++ gcc string-literals

我很难理解这段代码中的原因:

#include <cstdio>

void use(const char *msg) { printf("%s\n", msg); }

void bar() { use("/usr/lib/usr/local/foo-bar"); }
void foo() { use("/usr/local/foo-bar"); }

int main() {
    bar();
    foo();
}

编译器(在我的例子中是 GCC 4.9)决定共享字符串文字:

$ g++ -O2 -std=c++11 foo.cpp && strings a.out | grep /usr/
/usr/lib/usr/local/foo-bar

但在相同但不同的情况下:

#include <cstdio>

void use(const char *msg) { printf("%s\n", msg); }

void bar() { use("/usr/local/var/lib/dbus/machine-id"); } // CHANGED
void foo() { use("/var/lib/dbus/machine-id"); }           // CHANGED

int main() {
    bar();
    foo();
}

它没有:

$ g++ -O2 -std=c++11 foo.cpp && strings a.out | grep /lib/
/usr/local/var/lib/dbus/machine-id
/var/lib/dbus/machine-id

编辑:

对于 -Os,第二对字符串也被共享。但这没有意义。只是传递指点。具有常量偏移量的 lea 很难被认为是性能恶化,只允许在空间优化模式下共享。

字符串文字共享似乎有大小限制(30,包括终止 NUL)。这也没什么意义,除了可能避免链接器运行过长,试图找到常见的后缀。

最佳答案

This论文对 gcc 和这个主题有很好的研究。我个人并不知道 -fmerge-all-constants,但您可以检查这是否使字符串在两种情况下重叠(正如论文所述,它不适用于 O3Os)。

编辑

由于有一个有效的评论,答案是仅链接(我的意思是答案更多的只是相关信息而不是实际答案),我觉得我需要使它更广泛。所以我在 http://gcc.godbolt.org/ 中尝试了两个样本看看生成了什么程序集,因为我没有可访问的 Linux 机器。奇怪的是 gcc 4.9 不合并字符串(或者我的汇编知识完全错误),所以问题是 - 它是否特定于您的工具链或者解析工具可能失败?见下图:

enter image description here enter image description here

当然,如果我对程序集的理解是错误的,.LC1.LC3 仍然可以在 .rodata 部分重叠,那么这并不能证明什么,但至少有人会纠正我,我会意识到这一点。

关于c++ - 与 GCC 共享不一致的字符串文字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31450680/

相关文章:

c++ - 指向数组重叠数组末端的指针

Visual Studio Code、gcc、Mac 的 C/C++ 扩展 : "variable uint32_t is not a type name"

c++ - "multiple definition of ` 与 DLL 链接时 atexit '"

c - 结构上的指定初始化程序会导致 strcpy 和 realloc 中出现段错误

c++ - 用行对列进行排序

c++ - preLaunchTask 和 launch 可以在 VSCode 的同一个终端内启动吗?

c++ - CRITICAL_SECTION 并避免包含 windows.h?

c - + 零索引的地址,然后在某些情况下或总是在 C 中取消引用、未定义行为?

c++ - Intellisense 期望 ';' 带有多行字符串文字

arrays - 指向数组的指针,循环时每隔一段时间跳转一个索引