为什么编译器会在二进制文件中留下内联函数的实现?
Why would the compiler leave in the binary the implementation of an inlined function?
考虑这段简单的代码:
#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;
}
我用 Visual Studio 2015 在 "Debug" 和 "RelWithDebInfo" 模式下编译。
然后我使用覆盖率验证工具(Software verify - Coverage Validator)。
对于 Debug 构建,该工具报告 100% 的覆盖率
对于 RelWithDebInfo 构建,该工具报告了 66.67% 的覆盖率。它报告函数 Utl::GetInstance()
尚未执行。
由于 RelWithDebInfo 已优化,我怀疑这是因为该函数已被编译器内联(我不熟悉汇编代码来验证这一点,但我可以 post 如果有人向我解释如何检查这个,任何有帮助的东西)。但是当我使用 Software verify 的 DbgHelp 浏览器工具时,这个工具报告二进制文件中存在 Utl::GetInstance()
。
是否有可能 Visual Studio 内联了 Utl::GetInstance()
函数的代码,但还在二进制文件中保留了 "real" Utl::GetInstance()
(然后可能以这个的两个实现结束代码)?这可以解释为什么该工具报告我该函数从未被调用,而它的代码肯定已被执行...
任何具有全局范围的函数都需要有一个可调用函数和内联函数,所以会有重复。
在构建时将 "Inline function expansion" 设置为 "Disabled (/Ob0)" 允许 OP 获得 100% 的测试覆盖率。
考虑这段简单的代码:
#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;
}
我用 Visual Studio 2015 在 "Debug" 和 "RelWithDebInfo" 模式下编译。
然后我使用覆盖率验证工具(Software verify - Coverage Validator)。
对于 Debug 构建,该工具报告 100% 的覆盖率
对于 RelWithDebInfo 构建,该工具报告了 66.67% 的覆盖率。它报告函数 Utl::GetInstance()
尚未执行。
由于 RelWithDebInfo 已优化,我怀疑这是因为该函数已被编译器内联(我不熟悉汇编代码来验证这一点,但我可以 post 如果有人向我解释如何检查这个,任何有帮助的东西)。但是当我使用 Software verify 的 DbgHelp 浏览器工具时,这个工具报告二进制文件中存在 Utl::GetInstance()
。
是否有可能 Visual Studio 内联了 Utl::GetInstance()
函数的代码,但还在二进制文件中保留了 "real" Utl::GetInstance()
(然后可能以这个的两个实现结束代码)?这可以解释为什么该工具报告我该函数从未被调用,而它的代码肯定已被执行...
任何具有全局范围的函数都需要有一个可调用函数和内联函数,所以会有重复。
在构建时将 "Inline function expansion" 设置为 "Disabled (/Ob0)" 允许 OP 获得 100% 的测试覆盖率。