为什么编译器会在二进制中留下嵌套函数的实现

Why would the compiler leave in the binary the implementation of an inlined function?

本文关键字:嵌套 函数 实现 编译器 二进制 为什么      更新时间:2023-10-16

考虑这件简单的代码:

#include <iostream>
#include <sstream>
class Utl
{
public:
    // singleton accessor
    static Utl& GetInstance();
    virtual std::string GetHello( bool full ) = 0;
};
class UtlImpl : public Utl
{
public:
    UtlImpl() {}
    virtual std::string GetHello( bool full )
    {
        return (full)?"full":"partial";
    }
};
Utl& Utl::GetInstance()
{
    static UtlImpl instance;
    return instance;
}
int main( int argc, char* argv[] )
{
    std::cout << Utl::GetInstance().GetHello(true) << std::endl;  
    std::cout << Utl::GetInstance().GetHello(false) << std::endl;
    return 0;
}

i在"调试"answers" relwithdebinfo"模式中使用Visual Studio 2015编译。

然后,我使用覆盖范围验证工具(软件验证 - 覆盖范围验证器)。

对于 debug 构建,该工具报告了100%的覆盖范围

对于 relwithdebinfo 构建,该工具报告的覆盖率为66.67%。它报告了尚未执行功能Utl::GetInstance()

AS relwithdebinfo 已进行了优化,我怀疑这是因为编译器已将函数嵌入(我不熟悉汇编代码来验证这一点)解释我如何检查)。但是,当我使用Software验证的DBGHELP浏览器工具时,该工具报告了二进制中存在Utl::GetInstance()

Visual Studio是否有可能将Utl::GetInstance()函数的代码联合,但在二进制中还保留了"真实" Utl::GetInstance()(然后可能以此代码的两个实现结束)?这将解释为什么该工具报告我从未调用该函数,而其代码肯定已执行...

具有全局范围的任何函数都需要具有可呼叫函数以及内线函数,因此会有重复。

设置"内联函数扩展"到"禁用(/ob0)"构建允许OP获得测试100%的覆盖范围。