我有一个我不久前制作的旧 C++ 项目。嗯,它是一个 CPU 模拟器。每当我的代码中发生 CPU 故障(例如被零除或调试断点中断等)时,它只会执行 throw
并且在我的主循环中我有这样的事情:
try{
*(uint32_t*)&op_cache=ReadDword(cCS,eip);
(this->*Opcodes[op_cache[0]])();
eip=(uint16_t)eip+1;
}
catch(CpuInt_excp err){
err.code&=0x00FF;
switch(err.code){
case 0:
case 1: //.....
Int16(err.code);
break;
default:
throw CpuPanic_excp("16bit Faults",(err.code|0xF000)|TRIPLE_FAULT_EXCP);
break;
}
}
还有一个简单的操作码示例(凭空而来)
if(**regs16[AX]==0){
throw CpuInt_excp(0); //throw divide by zero error
}
这段代码基本上只是读取操作码,如果发生异常,则调用适当的中断(在 CPU 中,这只会更改 EIP)
嗯,这是在主循环中,try{}catch{}
开销确实增加了。这不是过早的优化,我分析了它和 gcc 的异常辅助函数(甚至没有做任何错误,因此没有抛出)并且辅助函数占用了长时间运行的模拟程序总执行时间的 10% 以上。
所以! 在这种情况下,替换异常的最佳方法是什么?我宁愿不必跟踪返回值,因为我已经编写了大量代码,而且跟踪它们确实是当功能变得非常深时,这很困难。
最佳答案
你还没有展示你的循环,但我猜在伪代码中它是:
while (some_condition) {
// Your try..catch block:
try {
// Do an op
}
catch (CpuInt_excp err) {
// Handle the exception
}
}
您可以将 try..catch
移出一个级别:
done = false;
while (!done) {
try {
while (some_condition) {
// Do an op
}
done = true;
}
catch (CpuInt_excp err) {
// Handle the exception
}
}
我已经包含了两个循环,因为我假设如果发生异常你希望能够继续(如果不知道你在 Int16
中做什么很难说,但我认为您允许在非 panic 异常之后继续进行)。自然不需要进行下去,循环一个就可以了。
外层循环只是在异常之后重新开始。它可以检查与内部循环相同的条件,如果该条件的检查成本不高(例如,它是一个程序计数器或其他东西),或者如果条件的检查成本很高,它可以像上面那样有一个标志。
关于c++ - 替换大量异常使用的最佳方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2167093/