我正在维护相当旧的旧代码。我的先驱在异常处理方面处于先驱地位(<2000)。处理非标准行为的抛出和捕获逻辑似乎已经奏效。
他们实现了一种不错的抛出方法:
TL_THROW_EXCEPTION(ISQL_MSG_XML_PARSER_ERROR) << msg;
TL_THROW_EXCEPTION扩展为:
TLThrowTec::CTLThrowExceptionTechnical::ThrowT(__FILE__,__LINE__,
ISQL_MSG_XML_PARSER_ERROR) << msg;
它将在堆栈上创建一个TLThrowTec :: CTLThrowExceptionTechnical实例,并通过移位操作来设置消息字符串。析构函数创建并引发异常。
stackoverflow中的2008年条目解释了该年的状态: throwing exceptions out of a destructor当时似乎奏效了。
但是现在Visual Studio 17允许抛出,但不再捕获。
由于遗留代码是整个系统的一部分,因此它会生成日志文件条目,例如“未处理的操作系统异常”。
我想在不对源代码进行太多更改的情况下恢复catch逻辑。最好是为TL_THROW_EXCEPTION提供#define。
有没有一种方法可以重新定义宏,以便在消息中引发异常?
如果我搜索TL_THROW_EXCEPTION,这是最后一行:
匹配行:770个匹配文件:217搜索到的文件总数:3159
我不喜欢全部触摸。
答案 0 :(得分:1)
现代C ++默认将所有析构函数指定为非抛出。并且,如果从指定为非抛出的任何函数引发了异常,则该程序将立即终止。这是因为抛弃析构函数的想法是令人讨厌的。在堆栈展开期间会自动调用析构函数,而已在传输异常。在这种情况下,再次抛出将自身终止程序。并且所有标准容器都会警告UB,如果包含对象的析构函数曾经抛出过。
但是您的用例不容易触发任何这种情况。 ThrowT
对象在我看来是要创建为立即抛出某些东西的临时对象,它们不会徘徊在分解其他对象时调用其析构函数。因此,我们可以将它们标记为再次抛出以恢复功能。像这样...
ThrowT::~ThrowT() noexcept(false) {
// as before
}
...将使宏再次工作。
答案 1 :(得分:0)
是否可以重新定义宏?
是的,只需取消定义,然后重新定义,例如:
#undef TL_THROW_EXCEPTION
#define TL_THROW_EXCEPTION ...
当然,如果您能想到一种使其成为class
或函数的方法,则最好在#undef
之后再执行此操作,而不是使用宏。
更像是:
#undef TL_THROW_EXCEPTION
class TL_THROW_EXCEPTION
{ ... }
然后定义构造函数以创建一个可以提供所需行为的实例。
答案 2 :(得分:0)
只需将异常产生类型调整为 be 异常,并使用:
public interface DataProcessor {
public boolean supports(MyInput input);
public MyOutput process(MyInput input);
}
@Service
public class YesDataProcessor implements DataProcessor {
public boolean supports(MyInput input) {
return input.getSomething().equals("yes");
}
public MyOutput process(MyInput input) {
// ... transforming to output
return
}
}
@Service
public class NoDataProcessor implements DataProcessor {
public boolean supports(MyInput input) {
return input.getSomething().equals("no");
}
public MyOutput process(MyInput input) {
// ... transforming to output
return output;
}
}
@Service
public class MyDataProcessorRegistry {
@Autowired
private List<DataProcessor> processors;
public Optional<DataProcessor> getProcessor(MyInput input) {
return processors.stream().filter(p -> p.supports(input)).findFirst();
}
}
由于#undef TL_THROW_EXCEPTION
#define TL_THROW_EXCEPTION(msg_) \
throw YourExceptionType(__FILE__, __LINE__, (msg_))
的优先级比throw
低,因此这将首先计算聚合表达式,然后抛出其结果。
答案 3 :(得分:0)
只需修复该类:
std::uncaught_exceptions()
(复数,不是单数)的结果保存在ctor中。noexcept(false)
以启用传播异常。std::uncaught_exceptions()
时才返回dtor返回保存的计数。否则,尝试构建异常会导致异常,然后将自己扔进混乱中将被std::terminate
调用。我希望您的构造函数使用std::stringstream
。否则,也可以考虑修复该疏忽。