我想告诉VC ++编译器来编译所有代码。能做到吗

时间:2020-03-06 14:27:33  来源:igfitidea点击:

我将VS2005 VC ++用于非托管C ++。我有VSTS,并且正在尝试使用代码覆盖率工具来完成有关单元测试的两件事:

  • 看看我正在测试的参考代码有多少正在执行
  • 查看我正在测试的代码中有多少种方法(如果有的话)根本没有进行单元测试

设置VSTS代码覆盖率工具(请参阅链接文本)并完成任务#1很简单。但是,#2对我来说是一个令人惊讶的挑战。这是我的测试代码。

class CodeCoverageTarget
{
public:
    std::string ThisMethodRuns() {
         return "Running";
    }

    std::string ThisMethodDoesNotRun() {
        return "Not Running";
    }
};

#include <iostream>
#include "CodeCoverageTarget.h"
using namespace std;
int main()

{
    CodeCoverageTarget cct; 
    cout<<cct.ThisMethodRuns()<<endl;
}

当在上述类中同时定义了这两种方法时,编译器会自动从obj文件中消除ThisMethodDoesNotRun()。如果我将其定义移到类之外,则它将包含在obj文件中,并且代码覆盖率工具显示它根本没有被执行。在大多数情况下,我希望编译器为我执行此消除操作,但是对于代码覆盖率工具而言,它会使值失去很大一部分(例如,找到未经测试的方法)。我已经尝试了很多方法来告诉编译器对我不再聪明,并且对所有内容进行编译,但是我感到很困惑。如果代码覆盖率工具对此进行了补偿(我想通过扫描源并将其与链接器输出进行匹配)会很好,但是我没有发现任何暗示它可以打开特殊模式的信息。我是否在这里完全遗漏了一些简单的东西,还是使用VC ++编译器+ VSTS代码覆盖工具无法做到这一点?

提前致谢,
克格勃

解决方案

关闭功能的内联。最简单的方法是在Debug模式下进行编译。

编辑:看到澄清后,我发现我的答案有误。也许如果我们使用" inline"关键字将函数的主体移到了.h文件的另一部分中?

抱歉,我应该澄清一下,我正在构建带有内联和所有优化功能的调试模式。此外,由于甚至从未考虑将代码视为内联对象,因此在进行内联之前就已删除了代码。

我们可以尝试仅在某些条件为真的情况下添加一行代码来调用该函数,并确保该条件永远不会为真。只要确保编译器无法弄清楚。例如,

int main(int argc, char **argv)
{
  if(argv == NULL)  // C runtime says this won't happen
    someMethodWhichIsntReallyEverCalled();
}

另一个选择是使用.inl文件根据构建在内联函数和非内联函数之间进行切换,如下所示:

在foo.inl文件中:

inline std::string Foo::ThisMethodDoesNotRun()
{
    return "Not Running";
}

在foo.h中:

#if !COVERAGE_BUILD
#include "foo.inl"
#endif

在foo.cpp中:

#if COVERAGE_BUILD
#define inline
#include "foo.inl"
#endif

确保不放弃功能的一种方法是将其导出。我们可以通过在函数声明中添加__declspec(dllexport)来实现。最好将其包装在C预处理器宏中,以便可以将其关闭,因为它是特定于编译器的,并且我们可能不希望所有构建都导出符号。导出函数的另一种方法是创建一个.DEF文件。

如果内联是问题所在,则我们可以使用__declspec(noinline)取得成功。

代码是否在静态库中,然后将其编译成测试EXE / DLL?链接器将自动丢弃静态库中未引用的目标文件。示例:如果静态库包含a.objb.obj以及我们将其链接到b.obj中的引用符号而不是a.obj中的EXE / DLL,则内容a.obj将不会链接到可执行文件或者DLL中。但是,重新阅读描述后,听起来好像不是这里发生的那样。