【发布时间】:2018-04-17 19:57:03
【问题描述】:
我有这样的功能:
bool op1();
bool op2();
bool foo() {
CoInitialize(nullptr);
if (!op1()) {
CoUninitialize();
return false;
}
// do more stuff, then call op2...
if (!op2()) {
CoUninitialize();
return false;
}
// happy path
CoUninitialize();
return true;
}
我想重构foo() 来抛出异常:
void foo() {
CoInitialize(nullptr);
if (!op1()) {
CoUninitialize(); // I'm lazy, can't I automate this call?
throw std::exception("Failed");
}
// ...
但我每次遇到错误都必须致电CoUninitialize()。
我曾想过将 COM 初始化调用封装在一个类中,所以析构函数 will do the cleanup,但是有一个未使用的对象对我来说感觉很奇怪:
class comlib {
public:
comlib() { CoInitialize(nullptr); }
~comlib() { CoUninitialize(); } // automated!
};
void foo() {
comlib nobodyEverCallsMe;
if (!op1()) {
throw std::exception("Failed");
}
// ...
有更好的方法吗?
【问题讨论】:
-
重要提示是确保
CoUninitialize()不会因为linkedin.com/pulse/…而抛出 -
最好在启动 exe 时调用
CoInitialize和在清理时调用CoUninitialize。但不是在任意时间的某个函数内。 -
如果你在 dll 中编码 - 你根本不能调用
CoInitialize/CoUninitialize。如果 exe 代码已经用另一个COINIT值调用CoInitializeEx会怎样? -
写一个“智能”类是要走的路,恕我直言,你可以使用 Raymon Chen 的:blogs.msdn.microsoft.com/oldnewthing/20040520-00/?p=39243
-
您的 RAII 包装器存在错误。如果
CoInitialize失败,您仍然会从d'tor 调用CoUninitialize。要解决此问题,您需要从您的 c'tor 中抛出,以防CoInitialize失败。还可以考虑在该 RAII 包装器上使用 [[maybe_unused]] 属性说明符 (C++17),这样您的编译器就不会发出警告。
标签: c++ winapi exception exception-handling com