Visual Studio 为新的初始化程序提供部分代码覆盖
Visual Studio gives partial code coverage for new initializers
我正在使用 Visual Studio 2015 Update 3
。
我无法在这个简单的 Unit Test
:
上获得 100% 的代码覆盖率
TEST_METHOD(New)
{
int* test = new int(4); //shows the line as partially covered
int* test2 = new int; //shows line as 100% covered
}
如果语句也在测试函数调用的代码中,就会发生这种情况。
与项目默认设置不同的唯一设置是 /profile
开关,这是让任何代码覆盖首先起作用所必需的。
我注意到 new
在没有 initializer
的情况下使用时显示 100%
覆盖率,但是对于 类 我通常会立即初始化它们,我想找到一个在不减少代码覆盖率的情况下做到这一点的方法。
代码反汇编
int* test = new int(4); //shows the line as partially covered
0F951D53 push 4
0F951D55 call operator new (0F9512B2h)
0F951D5A add esp,4
0F951D5D mov dword ptr [ebp-0ECh],eax
0F951D63 cmp dword ptr [ebp-0ECh],0
0F951D6A je UnitTest1::UnitTest1::New+56h (0F951D86h)
0F951D6C mov eax,dword ptr [ebp-0ECh]
0F951D72 mov dword ptr [eax],4
0F951D78 mov ecx,dword ptr [ebp-0ECh]
0F951D7E mov dword ptr [ebp-100h],ecx
0F951D84 jmp UnitTest1::UnitTest1::New+60h (0F951D90h)
0F951D86 mov dword ptr [ebp-100h],0
0F951D90 mov edx,dword ptr [ebp-100h]
0F951D96 mov dword ptr [test],edx
int* test2 = new int; //shows line as 100% covered
0F951D99 push 4
0F951D9B call operator new (0F9512B2h)
0F951DA0 add esp,4
0F951DA3 mov dword ptr [ebp-0F8h],eax
0F951DA9 mov eax,dword ptr [ebp-0F8h]
0F951DAF mov dword ptr [test2],eax
查看代码,我猜测 jmp
语句导致代码覆盖率分析工具将某些语句视为未命中。
您似乎有一个选项,这意味着 new
始终表现为 new(nothrow)
(换句话说,如果 new
returns nullptr
分配失败)。
程序集正在检查 operator new
是否有 returned nullptr(如果有,则不在 returned 地址存储 4)。您需要测试分配失败的情况,以便获得完整的覆盖率。在 C++ 中,程序集如下所示:
int * test;
int * tmp = operator new(sizeof(int));
if (tmp != nullptr) {
*tmp = 4;
test = tmp;
} else {
test = nullptr;
}
编辑
啊哈!在 this blog post 中,Microsoft 解释说,新生成的代码一直在测试空值 return, 以防万一 link 在 nothrow
版本中 。对于 VC2015,他们提供了一个选项,可以说“不要费心去做,new
会抛出,它永远不会 return nullptr
.
所以,为了避免不必要的分支,在编译选项中添加:/Zc:throwingNew
。 (这通常也有助于提高性能。)
我正在使用 Visual Studio 2015 Update 3
。
我无法在这个简单的 Unit Test
:
TEST_METHOD(New)
{
int* test = new int(4); //shows the line as partially covered
int* test2 = new int; //shows line as 100% covered
}
如果语句也在测试函数调用的代码中,就会发生这种情况。
与项目默认设置不同的唯一设置是 /profile
开关,这是让任何代码覆盖首先起作用所必需的。
我注意到 new
在没有 initializer
的情况下使用时显示 100%
覆盖率,但是对于 类 我通常会立即初始化它们,我想找到一个在不减少代码覆盖率的情况下做到这一点的方法。
代码反汇编
int* test = new int(4); //shows the line as partially covered
0F951D53 push 4
0F951D55 call operator new (0F9512B2h)
0F951D5A add esp,4
0F951D5D mov dword ptr [ebp-0ECh],eax
0F951D63 cmp dword ptr [ebp-0ECh],0
0F951D6A je UnitTest1::UnitTest1::New+56h (0F951D86h)
0F951D6C mov eax,dword ptr [ebp-0ECh]
0F951D72 mov dword ptr [eax],4
0F951D78 mov ecx,dword ptr [ebp-0ECh]
0F951D7E mov dword ptr [ebp-100h],ecx
0F951D84 jmp UnitTest1::UnitTest1::New+60h (0F951D90h)
0F951D86 mov dword ptr [ebp-100h],0
0F951D90 mov edx,dword ptr [ebp-100h]
0F951D96 mov dword ptr [test],edx
int* test2 = new int; //shows line as 100% covered
0F951D99 push 4
0F951D9B call operator new (0F9512B2h)
0F951DA0 add esp,4
0F951DA3 mov dword ptr [ebp-0F8h],eax
0F951DA9 mov eax,dword ptr [ebp-0F8h]
0F951DAF mov dword ptr [test2],eax
查看代码,我猜测 jmp
语句导致代码覆盖率分析工具将某些语句视为未命中。
您似乎有一个选项,这意味着 new
始终表现为 new(nothrow)
(换句话说,如果 new
returns nullptr
分配失败)。
程序集正在检查 operator new
是否有 returned nullptr(如果有,则不在 returned 地址存储 4)。您需要测试分配失败的情况,以便获得完整的覆盖率。在 C++ 中,程序集如下所示:
int * test;
int * tmp = operator new(sizeof(int));
if (tmp != nullptr) {
*tmp = 4;
test = tmp;
} else {
test = nullptr;
}
编辑
啊哈!在 this blog post 中,Microsoft 解释说,新生成的代码一直在测试空值 return, 以防万一 link 在 nothrow
版本中 。对于 VC2015,他们提供了一个选项,可以说“不要费心去做,new
会抛出,它永远不会 return nullptr
.
所以,为了避免不必要的分支,在编译选项中添加:/Zc:throwingNew
。 (这通常也有助于提高性能。)