gpt4 book ai didi

c++ - glibc 函数的 GCC、-flto、-fno-builtin 和自定义函数实现

转载 作者:太空宇宙 更新时间:2023-11-04 01:45:51 26 4
gpt4 key购买 nike

我观察到带有 GCC 标志 -flto 的意外行为(至少我找不到解释)和 jemalloc/tcmalloc .一次-flto被使用并且我链接到上面的库 malloc/calloc 并且 friend 没有被 je/tc malloc 替换实现,调用glibc实现。一旦我删除 -flto标志,一切都按预期工作。我尝试使用 -fno-builtin/-fno-builtin-*-flto但是,它仍然没有选择 je/tc malloc执行。
-flto机械工程?为什么二进制不选择新的实现?它甚至如何与 -fno-builtin 链接当它应该在 Unresolved external 失败时,例如 printf ?

编辑001:
海合会 7.3
示例代码

int main()
{
auto p = malloc(1024);
free(p);
return 0;
}

汇编:

/usr/bin/c++ -O2 -g -DNDEBUG -flto -std=gnu++14 -o CMakeFiles/flto.dir/main.cpp.o -c /home/user/Development/CPPJunk/flto/main.cpp



链式:

/usr/bin/c++ -O2 -g -DNDEBUG -flto CMakeFiles/flto.dir/main.cpp.o -o flto -L/home/user/Development/jemalloc -Wl,-rpath,/home/user/Development/jemalloc -ljemalloc



编辑002:
更合适的示例代码
#include <cstdlib>

int main()
{
auto p = malloc(1024);
if (p) {
free(p);
}

auto p1 = new int;
if (p1) {
delete p1;
}

auto p2 = new int[32];
if (p2) {
delete[] p2;
}
return 0;
}

最佳答案

首先,您的示例代码是错误的。仔细阅读 C11 标准 n1570 .当您想使用标准 malloc , 你应该 #include <stdlib.h> .

在 C++11 中(阅读 n3337)malloc不赞成使用,不应使用(首选 new )。如果你还想用 std::malloc 在 C++ 中你应该 #include <cstdlib> (在 GCC 中,内部包含 <stdlib.h> )

那么您的示例代码几乎是 C 代码(一旦将 auto 替换为 void* ),而不是 C++。可能是 optimized (一旦你包括 <stdlib.h> ),即使没有 -flto但只有 -O3 ,根据 as-if规则,为空 main . (我什至写了一份公开报告,bismon-chariot-doc.pdf,其中有一节 §1.4.2 在几页中解释了优化是如何发生的)。

围绕 malloc 进行优化和 free , GCC 使用了一些 __attribute__(malloc) function attribute<stdlib.h> 的声明中(在 malloc 内) .

How the -flto machinery works?



LTO 在 GCC internals §25 中进行了解释.

它通过在“编译”和“链接”时使用代码的一些内部( GIMPLE -like 和/或 SSA -like)表示来工作(实际上,链接步骤变成了另一个具有全程序优化的编译,因此您的代码在实践中会被“编译”两次)。

在编译和链接时,LTO 总是应该(在实践中)与一些优化标志(例如 -O2 甚至 -O3 )一起使用。所以你应该编译和链接 g++ -flto -O2 (使用 -flto 没有至少 -O2 没有实际意义,并且应该在编译和链接时使用完全相同的优化标志)。

更准确地说 -flto还在目标文件中嵌入源代码的一些内部( GIMPLE 类)表示,这也用于“链接时”(特别是 optimizationinlining 在“链接”整个程序时再次发生,重新使用它的 GIMPLE)。实际上 GCC 包含一些 LTO 前端和编译器,称为 lto1 (除了名为 cc1plus 的 C++ 前端和编译器)和 lto1是(当您与 g++ -flto -O2 链接时)在链接时用于重新处理这些 GIMPLE 表示。

可能, libjemalloc有自己的标题,并且可能有 inline (或内联)函数。那你还需要使用 -flto -O2从源代码编译该库时(以便将其 Gimple 存储在库中)

最后,通常的 malloc被调用独立于 -flto .这是一个链接器问题,而不是编译器问题。您可以尝试链接 -ljemalloc静态地(然后你最好用 gcc -flto -O2 构建该库;如果你不这样构建它,你将不会在 malloc 调用中获得 LTO 优化)。

你也可以通过 -v到您的编译和链接命令以了解 g++是在做。你甚至可以通过 -Wl,--verboseld (由 g++ 开始)是冗长的。

请注意,LTO(以及它使用的内部表示)是特定于编译器和版本的。内部 (Gimple & SSA ) 表示在 GCC 7 之间略有不同& GCC 8 (在 Clang 中它非常不同,所以当然不兼容)。动态链接器 ld-linux(8)不知道LTO。

PS。您可以安装 libjemalloc-dev打包并添加 #include <jemalloc/jemalloc.h>在你的代码中。另见 jemalloc(3)手册页。大概 libjemalloc可以配置或修补以定义一些 je_malloc malloc 的替代符号.那么使用 je_malloc 会更简单(对于 LTO)在您的代码中(以避免几个 malloc ELF 符号之间的冲突)。要了解有关共享库中符号的更多信息,请阅读 Drepper 的 How to Write Shared Libraries纸。当然,您应该期望 LTO 改变链接行为!

关于c++ - glibc 函数的 GCC、-flto、-fno-builtin 和自定义函数实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53904726/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com