C++ glibc函数的GCC、-flto、-fno内置函数和自定义函数实现

C++ glibc函数的GCC、-flto、-fno内置函数和自定义函数实现,c++,c,gcc,compilation,linkage,C++,C,Gcc,Compilation,Linkage,我正在观察GCC标志-flto和jemalloc/tcmalloc的意外行为(至少我找不到解释)。一旦使用了-flto,并且我与上述库malloc/calloc和friends的链接没有被je/tc malloc实现所取代,就会调用glibc实现。一旦我删除-flto标志,一切都会按预期进行。我尝试将-fno-builtin/-fno-builtin-*与-flto一起使用,但它仍然没有选择je/tc malloc实现 -flto机器是如何工作的?为什么二进制文件不选择新的实现?当它在未解决的外

我正在观察GCC标志
-flto
jemalloc
/
tcmalloc
的意外行为(至少我找不到解释)。一旦使用了
-flto
,并且我与上述库malloc/calloc和friends的链接没有被
je/tc malloc
实现所取代,就会调用glibc实现。一旦我删除
-flto
标志,一切都会按预期进行。我尝试将
-fno-builtin
/
-fno-builtin-*
-flto
一起使用,但它仍然没有选择
je/tc malloc
实现

-flto
机器是如何工作的?为什么二进制文件不选择新的实现?当它在未解决的外部问题(例如,
printf
)上出现故障时,它如何与
-fno-builtin
链接

EDIT001:
GCC 7.3
示例代码

int main()
{
    auto p = malloc(1024);
    free(p);
    return 0;
}
#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;
}
编译:

/usr/bin/c++-O2-g-DNDEBUG-flto-std=gnu++14-o CMakeFiles/flto.dir/main.cpp.o-c /home/user/Development/cppcrunk/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

EDIT002:
更合适的示例代码

int main()
{
    auto p = malloc(1024);
    free(p);
    return 0;
}
#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;
}
#包括
int main()
{
自动p=malloc(1024);
如果(p){
自由基(p);
}
自动p1=新整数;
如果(p1){
删除p1;
}
自动p2=新整数[32];
如果(p2){
删除[]p2;
}
返回0;
}

首先,您的示例代码是错误的。仔细阅读C11标准。当您想要使用标准的
malloc
时,您应该
#包括

在C++11(read)中,
malloc
不受欢迎,不应使用(首选
new
)。如果你还想在C++中使用,你应该<代码>包含< <代码>(在GCC中,它内部包括<代码> >

那么,你的样例代码几乎是C代码(一旦你用<代码> VoU**/COD>)替换<代码> Audio<代码>,而不是C++。根据规则,即使没有

-flto
,但只有
-O3
,它也可以(一旦包含
)到空的
main
。(我甚至写了一份公开报告,其中第§1.4.2节在几页中解释了优化是如何发生的)

为了优化
malloc
free
,GCC在
malloc
的声明(内部
)中使用了一些
\uuuu属性(malloc)

flto机器是如何工作的

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

在编译和链接时,LTO应始终(实际上)与一些优化标志一起使用(例如
-O2
甚至
-O3
)。因此,您应该编译并链接
g++-flto-O2
(使用
-flto
没有至少
-O2
,没有实际意义,并且应该在编译和链接时使用完全相同的优化标志)

更准确地说,
-flto
还将源代码的一些内部(-like)表示嵌入到目标文件中,并且也在“链接时”使用(尤其是在“链接”整个程序时,重复使用其框架时再次使用)。实际上,GCC包含了一些LTO前端和编译器,称为“代码> Lto1 < /Cube >(除了C++前端和编译器称为<代码> CcPulle)和<代码> LTO1(当您链接到<代码> G++-FLTO-O2/COD>)时,使用链接时间来重新处理这些GIMPLE表示。 可能,
libjemalloc
有自己的头,并且可能有
inline
(或inlineable)函数。然后,在从源代码编译该库时,还需要使用
-flto-O2
(以便将其Gimple存储在库中)

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

您还可以将
-v
传递给编译和链接命令,以了解
g++
在做什么。您甚至可以通过
-Wl,--verbose
请求
ld
(由
g++
启动)变得详细

请注意,LTO(及其使用的内部表示)是特定于编译器和版本的。内部(Gimple&)表示形式在&(在Clang中是非常不同的,所以当然不兼容)。动态链接器不知道LTO


另外,您可以安装
libjemalloc dev
包,并在代码中添加
#include
。另请参见手册页。可能可以配置或修补
libjemalloc
,以定义一些
je_malloc
符号作为
malloc
的替代品。然后(对于LTO)在代码中使用
je_malloc
(避免多个
malloc
符号之间的冲突)会更简单。要了解更多关于共享库中符号的信息,请阅读Drepper的论文。当然,您应该期望LTO改变链接的行为

请你发一封邮件好吗?你没有提供足够的细节。您应该指定gcc版本、用于生成此命令行的命令行以及可以演示此行为的代码。@Groo您知道了吗?您是否也使用
-flto
编译了
libjemalloc
?没有。。。我应该吗?为什么?例如,我想我所有的
boost
库都不是共同的