方法,用于在代码中唯一标识方法调用,以测试调用序列是否未更改
Method to uniquely identify a method call in code, to test that a sequence of calls is unchanged
我们正在开发一个新的中断系统(用 c++ 中),以取代旧的不一致系统。
它的工作原理是这样的:
-
想要使方法可中断的程序员接受
BreakFlag
对象作为方法的参数。 -
在方法过程中,程序员检查
break_flag.is_set()
,如果是,则退出并整理。
我们希望能够 te 测试在对程序进行一些更改后,所有对break_flag.is_set()
的原始调用都保持相同的顺序。(我们将同一循环中的多个调用计为一个调用,因此两个不同大小的操作看起来是相同的)
我们的第一种方法是使用调用堆栈来标识每个实例。例如在代码中:
void A(BreakFlag& flag) {
flag.is_set();
B(flag);
C(flag);
}
void B(BreakFlag& flag) {
flag.is_set();
C(flag);
}
void C(BreakFlag& flag) {
flag.is_set();
}
每次调用调用is_set
时,我们都会查看调用堆栈,并为此方法生成以下序列:
A
A, B
A, B, C
A, C
然后,我们可以使用它来检查每次测试程序时检查的顺序,以便有人无法来执行此操作:
void A(BreakFlag&flag) { flag.is_set(); B(旗帜); C(旗帜); }
void B(BreakFlag& flag) {
flag.is_set();
//C(flag); // I HAVE COMMENTED THIS OUT BECAUSE I DONT LIKE FLAG!
}
void C(BreakFlag& flag) {
flag.is_set();
}
因为它会导致以下顺序:
A
A, B
A, C
这与我们的原版不符。
我们遇到的问题是,编译器有时会以调用堆栈更改的方式进行优化,这会导致我们提出的系统注册错误的失败测试,因为调用堆栈不是它所期望的,即使它是正确的。
我们可以通过执行类似于以下内容的操作来解决它:
#define CHECK_FLAG(x) actually_check_flag(__LINE__,__FILE__,x)
这将允许我们基本上在代码中识别每个实例。
除此之外,我们想不出任何方法来识别每个在优化代码中不会改变的.is_set
调用,对吗?
您可以使用 RAII 手动维护调用堆栈。 在进入每个函数时构造一个保护对象:
void B(BreakFlag& flag) {
BreakFlagStackGuard guard(flag, "B");
flag.is_set();
C(flag);
}
BreakFlagStackGuard
的构造函数将函数名称"B"
推送到flag.stack
上,而析构函数~BreakFlagStackGuard()
(当B
返回时将调用)弹出它。
无论编译器如何优化它,它都需要尊重您的保护对象,以便您可以保证观察到的调用堆栈反映源代码。
- 如何强制从重写方法调用重写的方法基方法?
- C++:使用方法调用析构函数的顺序是什么?
- 派生类调用父类的方法,该方法调用重写的虚拟方法调用错误的方法
- 使用 object 中的方法调用带有 std::bind 和 std::function.target 的 C 样式函数
- 指向类方法调用的指针
- 如何使用 SFINAE 在方法调用中有条件地定义变量?
- 是否有可以处理方法调用依赖关系的设计模式?
- 如何缩短C++中的方法调用?
- 从部分专用模板方法调用模板非静态方法
- 有没有办法禁止派生类中的基类方法调用?
- 为什么这C++只在编译器上编码一个不明确的方法调用Microsoft?
- 从父方法调用子方法
- 如何将子方法调用到父方法
- 虚拟函数在哪里使用 vpointer to vtable 来解析方法调用,非虚拟方法存储在哪里以及如何解析它们?
- 从静态方法调用静态函数指针
- 从同一类中的另一个方法调用方法时出错
- 方法调用意外地像 l 值一样起作用
- 无法从派生的一个方法调用基类方法
- 从类方法调用命名空间中名为 Same 的函数时,重载解析失败
- C 多线程JAVA JNI方法调用