- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
想了解一下GCC编译器在使用noexcept
时生成的分支或 throw()
用于标记非抛出函数。我知道 noexcept
之间的区别和 throw()
, 但无法弄清楚使用 throw()
时定义的附加分支是什么而不是 noexcept
以及如何提高覆盖率以达到 100% 的分支机构覆盖率?
测试示例类的代码片段:
class MyClass
{
public:
MyClass() noexcept :
iThrowFlag(false)
{}
void non_throwing_method() noexcept
{
try
{
throwing_method();
}
catch (...)
{
}
}
void throwing_method()
{
if (iThrowFlag)
{
throw std::exception();
}
}
public:
bool iThrowFlag;
};
定义了 2 个测试用例,都通过了:
non_throwing_method
底层时完成 throwing_method
不扔,non_throwing_method
底层时完成 throwing_method
正在抛出任何异常。下面是 GCC/GCOV 为上述代码生成的覆盖率报告,所有的行和分支都被覆盖了(覆盖了 4/4 个分支):
-: 0:Source:myclass.hh
-: 0:Graph:main.gcno
-: 0:Data:main.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include <iostream>
-: 2:#include <string>
-: 3:
-: 4:using namespace std;
-: 5:
-: 6:class MyClass
-: 7:{
-: 8:public:
function _ZN7MyClassC2Ev called 2 returned 100% blocks executed 100%
2: 9: MyClass() noexcept :
2: 10: iThrowFlag(false)
2: 11: {}
-: 12:
function _ZN7MyClass19non_throwing_methodEv called 2 returned 100% blocks executed 100%
2: 13: void non_throwing_method() noexcept
-: 14: {
-: 15: try
-: 16: {
2: 17: throwing_method();
call 0 returned 100%
branch 1 taken 50% (fallthrough)
branch 2 taken 50% (throw)
-: 18: }
1: 19: catch (...)
call 0 returned 100%
-: 20: {
-: 21: }
2: 22: }
-: 23:
function _ZN7MyClass15throwing_methodEv called 2 returned 50% blocks executed 100%
2: 24: void throwing_method()
-: 25: {
2: 26: if (iThrowFlag)
branch 0 taken 50% (fallthrough)
branch 1 taken 50%
-: 27: {
1: 28: throw std::exception();
call 0 returned 100%
call 1 returned 100%
call 2 returned 0%
-: 29: }
1: 30: }
-: 31:
-: 32:public:
-: 33: bool iThrowFlag;
-: 34:};
由于目标平台不支持 C++11 和 noexcept
, 它被交换为 throw()
说明符如下:
class MyClass
{
public:
MyClass() throw() :
iThrowFlag(false)
{}
void non_throwing_method() throw()
{
try
{
throwing_method();
}
catch (...)
{
}
}
void throwing_method()
{
if (iThrowFlag)
{
throw std::exception();
}
}
public:
bool iThrowFlag;
};
在带有已检查分支的 GCOV 输出下方 (5/8)。用 throw()
编码生成额外的 4 个分支,这些分支很难理解,也很难通过测试覆盖:
-: 0:Source:myclass.hh
-: 0:Graph:main.gcno
-: 0:Data:main.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include <iostream>
-: 2:#include <string>
-: 3:
-: 4:using namespace std;
-: 5:
-: 6:class MyClass
-: 7:{
-: 8:public:
function _ZN7MyClassC2Ev called 2 returned 100% blocks executed 100%
2: 9: MyClass() throw() :
2: 10: iThrowFlag(false)
2: 11: {}
-: 12:
function _ZN7MyClass19non_throwing_methodEv called 2 returned 100% blocks executed 75%
2: 13: void non_throwing_method() throw()
-: 14: {
-: 15: try
-: 16: {
2: 17: throwing_method();
call 0 returned 100%
branch 1 taken 50% (fallthrough)
branch 2 taken 50% (throw)
-: 18: }
1: 19: catch (...)
call 0 returned 100%
call 1 returned 100%
branch 2 taken 100% (fallthrough)
branch 3 taken 0% (throw)
branch 4 never executed
branch 5 never executed
call 6 never executed
-: 20: {
-: 21: }
2: 22: }
-: 23:
function _ZN7MyClass15throwing_methodEv called 2 returned 50% blocks executed 100%
2: 24: void throwing_method()
-: 25: {
2: 26: if (iThrowFlag)
branch 0 taken 50% (fallthrough)
branch 1 taken 50%
-: 27: {
1: 28: throw std::exception();
call 0 returned 100%
call 1 returned 100%
call 2 returned 0%
-: 29: }
1: 30: }
-: 31:
-: 32:public:
-: 33: bool iThrowFlag;
-: 34:};
测试用例如下(以获取有关该用例的完整详细信息):
void test1()
{
MyClass lObj;
lObj.non_throwing_method();
}
void test2()
{
MyClass lObj;
lObj.iThrowFlag = true;
lObj.non_throwing_method();
lObj.iThrowFlag = false;
}
如果有人对所描述的行为有答案/解释,我将不胜感激。
编辑:另附汇编代码(仅函数代码:`non_throwing_method1 进行比较)。
没有异常(exception):
_ZN7MyClass19non_throwing_methodEv:
.LFB1253:
.loc 2 13 0
.cfi_startproc
.cfi_personality 0x3,__gxx_personality_v0
.cfi_lsda 0x3,.LLSDA1253
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movq %rdi, -8(%rbp)
movq __gcov0._ZN7MyClass19non_throwing_methodEv(%rip), %rax
addq $1, %rax
movq %rax, __gcov0._ZN7MyClass19non_throwing_methodEv(%rip)
.loc 2 17 0
movq -8(%rbp), %rax
movq %rax, %rdi
.LEHB0:
call _ZN7MyClass15throwing_methodEv
.LEHE0:
movq __gcov0._ZN7MyClass19non_throwing_methodEv+8(%rip), %rax
addq $1, %rax
movq %rax, __gcov0._ZN7MyClass19non_throwing_methodEv+8(%rip)
.loc 2 22 0
jmp .L7
.L6:
movq %rax, %rdx
movq __gcov0._ZN7MyClass19non_throwing_methodEv+16(%rip), %rax
addq $1, %rax
movq %rax, __gcov0._ZN7MyClass19non_throwing_methodEv+16(%rip)
.loc 2 19 0
movq %rdx, %rax
movq %rax, %rdi
call __cxa_begin_catch
movq __gcov0._ZN7MyClass19non_throwing_methodEv+24(%rip), %rax
addq $1, %rax
movq %rax, __gcov0._ZN7MyClass19non_throwing_methodEv+24(%rip)
call __cxa_end_catch
movq __gcov0._ZN7MyClass19non_throwing_methodEv+32(%rip), %rax
addq $1, %rax
movq %rax, __gcov0._ZN7MyClass19non_throwing_methodEv+32(%rip)
.L7:
.loc 2 22 0
nop
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1253:
.globl __gxx_personality_v0
.section .gcc_except_table._ZN7MyClass19non_throwing_methodEv,"aG",@progbits,_ZN7MyClass19non_throwing_methodEv,comdat
.align 4
.LLSDA1253:
.byte 0xff
.byte 0x3
.uleb128 .LLSDATT1253-.LLSDATTD1253
.LLSDATTD1253:
.byte 0x1
.uleb128 .LLSDACSE1253-.LLSDACSB1253
.LLSDACSB1253:
.uleb128 .LEHB0-.LFB1253
.uleb128 .LEHE0-.LEHB0
.uleb128 .L6-.LFB1253
.uleb128 0x1
.LLSDACSE1253:
.byte 0x1
.byte 0
.align 4
.long 0
.LLSDATT1253:
.section .text._ZN7MyClass19non_throwing_methodEv,"axG",@progbits,_ZN7MyClass19non_throwing_methodEv,comdat
.size _ZN7MyClass19non_throwing_methodEv, .-_ZN7MyClass19non_throwing_methodEv
.section .text._ZN7MyClass15throwing_methodEv,"axG",@progbits,_ZN7MyClass15throwing_methodEv,comdat
.align 2
.weak _ZN7MyClass15throwing_methodEv
.type _ZN7MyClass15throwing_methodEv, @function
使用 throw():
_ZN7MyClass19non_throwing_methodEv:
.LFB1253:
.loc 2 13 0
.cfi_startproc
.cfi_personality 0x3,__gxx_personality_v0
.cfi_lsda 0x3,.LLSDA1253
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movq %rdi, -8(%rbp)
movq __gcov0._ZN7MyClass19non_throwing_methodEv(%rip), %rax
addq $1, %rax
movq %rax, __gcov0._ZN7MyClass19non_throwing_methodEv(%rip)
.loc 2 17 0
movq -8(%rbp), %rax
movq %rax, %rdi
.LEHB0:
call _ZN7MyClass15throwing_methodEv
.LEHE0:
movq __gcov0._ZN7MyClass19non_throwing_methodEv+8(%rip), %rax
addq $1, %rax
movq %rax, __gcov0._ZN7MyClass19non_throwing_methodEv+8(%rip)
.loc 2 22 0
jmp .L3
.L8:
movq %rax, %rdx
movq __gcov0._ZN7MyClass19non_throwing_methodEv+16(%rip), %rax
addq $1, %rax
movq %rax, __gcov0._ZN7MyClass19non_throwing_methodEv+16(%rip)
.loc 2 19 0
movq %rdx, %rax
movq %rax, %rdi
call __cxa_begin_catch
movq __gcov0._ZN7MyClass19non_throwing_methodEv+24(%rip), %rax
addq $1, %rax
movq %rax, __gcov0._ZN7MyClass19non_throwing_methodEv+24(%rip)
.LEHB1:
call __cxa_end_catch
.LEHE1:
movq __gcov0._ZN7MyClass19non_throwing_methodEv+32(%rip), %rax
addq $1, %rax
movq %rax, __gcov0._ZN7MyClass19non_throwing_methodEv+32(%rip)
.loc 2 22 0
jmp .L3
.L9:
cmpq $-1, %rdx
je .L7
movq __gcov0._ZN7MyClass19non_throwing_methodEv+48(%rip), %rdx
addq $1, %rdx
movq %rdx, __gcov0._ZN7MyClass19non_throwing_methodEv+48(%rip)
movq %rax, %rdi
.LEHB2:
call _Unwind_Resume
.L7:
movq __gcov0._ZN7MyClass19non_throwing_methodEv+40(%rip), %rdx
addq $1, %rdx
movq %rdx, __gcov0._ZN7MyClass19non_throwing_methodEv+40(%rip)
.loc 2 13 0
movq %rax, %rdi
call __cxa_call_unexpected
.LEHE2:
.L3:
.loc 2 22 0
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1253:
.globl __gxx_personality_v0
.section .gcc_except_table._ZN7MyClass19non_throwing_methodEv,"aG",@progbits,_ZN7MyClass19non_throwing_methodEv,comdat
.align 4
.LLSDA1253:
.byte 0xff
.byte 0x3
.uleb128 .LLSDATT1253-.LLSDATTD1253
.LLSDATTD1253:
.byte 0x1
.uleb128 .LLSDACSE1253-.LLSDACSB1253
.LLSDACSB1253:
.uleb128 .LEHB0-.LFB1253
.uleb128 .LEHE0-.LEHB0
.uleb128 .L8-.LFB1253
.uleb128 0x1
.uleb128 .LEHB1-.LFB1253
.uleb128 .LEHE1-.LEHB1
.uleb128 .L9-.LFB1253
.uleb128 0x3
.uleb128 .LEHB2-.LFB1253
.uleb128 .LEHE2-.LEHB2
.uleb128 0
.uleb128 0
.LLSDACSE1253:
.byte 0x1
.byte 0
.byte 0x7f
.byte 0
.align 4
.long 0
.LLSDATT1253:
.byte 0
.section .text._ZN7MyClass19non_throwing_methodEv,"axG",@progbits,_ZN7MyClass19non_throwing_methodEv,comdat
.size _ZN7MyClass19non_throwing_methodEv, .-_ZN7MyClass19non_throwing_methodEv
.section .text._ZN7MyClass15throwing_methodEv,"axG",@progbits,_ZN7MyClass15throwing_methodEv,comdat
.align 2
.weak _ZN7MyClass15throwing_methodEv
.type _ZN7MyClass15throwing_methodEv, @function
最佳答案
看来我要过一会儿再回答我自己的问题。
throw()
和 noexcept
之间的区别(从 C++11 到 C++17)非常大。
在运行时,如果异常将函数标记为throw()
调用堆栈展开到函数的调用者,然后调用 std::unexpected
来执行意外处理程序,最后(默认行为)程序由 std::terminate
.
对于 C++11,noexcept 运行时行为略有不同:调用堆栈只是可能在程序执行终止之前展开。没有调用 std::unexpected
。通常编译器只调用 std::terminate
而不会展开。
就是这样,这就是为什么 throw()
和 noexcept
函数生成不同的汇编代码以及代码覆盖工具测量不同结果的原因。
幸运的是,从 C++17 开始,就不会再有惊喜了,因为动态异常规范已被弃用并从标准中删除,而 throw()
规范仍然有效,但它与 noexcept(true)
.
关于c++ - GCC/GCOV 为使用 throw()/noexcept 的函数生成的不同分支覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43278010/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!