У меня есть старый проект C ++, который я сделал некоторое время назад. Ну, это эмулятор процессора. Всякий раз, когда происходит сбой процессора (например, деление на ноль, отладка прерывания точки останова и т. Д.) В моем коде, он просто делает 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
}
Что этот код делает в основном, так это просто читает код операции и, если возникла исключительная ситуация, затем вызывает соответствующее прерывание (в ЦПУ, которое просто меняет EIP)
Что ж, в основном цикле накладные расходы try{}catch{}
действительно складываются. Это не преждевременная оптимизация, я профилировал ее и вспомогательные функции исключений gcc (даже без каких-либо сбоев и, следовательно, без сбоев), а вспомогательные функции занимали более 10% от общего времени выполнения долго эмулируемой программы.
Так! Что было бы лучшим способом замены исключений в этом случае? Я бы предпочел не отслеживать отслеживаемые значения, потому что у меня уже написана тонна кода и потому, что отслеживать их действительно сложно когда функции становятся действительно глубокими.