如何在堆栈展开时调用函数
How can I call a function on stack unwind?
我想写的是
void foo()
{
int a = 5;
ExecuteOnUnwind eou(bind(&cleanupFunc, a));
}
使得当函数返回或抛出异常时调用cleanupFunc(a)
。有没有现成的设施可以帮我做这件事?我没能在谷歌上找到合适的短语,但似乎有一些东西可以做到这一点。如果没有,我就在下面快速整理出一个解决方案。奇怪的是,它似乎在发布模式下不起作用,但在vc10的调试中工作-我如何调整实现以使其在不冒额外调用临时的风险的情况下始终工作?
编辑:修复涉及使用shared_ptr;也减轻了对暂时破坏的担忧。新代码在
下面template <typename T>
struct ExecuteOnUnwindHelper
{
ExecuteOnUnwindHelper(const T & _functor) : mFunctor(_functor)
{
}
~ExecuteOnUnwindHelper()
{
mFunctor();
}
const T & mFunctor;
};
template <typename T>
boost::shared_ptr<ExecuteOnUnwindHelper<T>> ExecuteOnUnwind(const T & _functor)
{
return boost::shared_ptr<ExecuteOnUnwindHelper<T>>(new ExecuteOnUnwindHelper<T>(_functor));
}
void cleanupFunc(int a)
{
wcout << L"cleanup" << endl;
}
void foo()
{
int a = 5;
auto eou = ExecuteOnUnwind(boost::bind(&cleanupFunc, 5));
}
int main()
{
foo();
return 0;
}
编译器必须以某种方式优化堆栈上变量的创建,因为它认为它没有被使用。也许它只是内联了对函数的调用,跳过了创建/销毁部分(我想说这是最有可能的)。它认为全局语义是保留的,但它实际上不是一个安全的优化,如你的例子所示。
我认为这是一个错误的优化,因为它显然改变了高级语义。用不同的编译器进行测试会很有趣。当我在家里有机会的时候,我会尝试VS2012。
无论如何,要强制它通过创建/销毁序列,只需使用boost::shared_ptr
,它将负责创建对象并在对象超出作用域时销毁它,无论是通过return
语句还是通过异常抛出。
最简单的解决方案是将所需的功能放入类型的析构函数中。在您的情况下,不需要自动/智能指针,堆栈将是足够的,并且可能会消除您可能遇到的编译器问题。
class ExecuteOnUnwind
{
public:
~ExecuteOnUnwind()
{
/** Do something */
}
int data;
};
void foo()
{
ExecuteOnUnwind runOnExit;
/** Functions code here */
runOnExit.data = 5;
}
如果这不起作用,那么你可以禁用受影响代码的优化(即析构函数):
#pragma optimize( "", off )
...
#pragma optimize( "", on )
相关文章:
- 如何用参数值调用函数(仅在运行时已知)
- 从python中调用C++函数并获取返回值
- 当使用通配符和null指针调用函数时,对输出的说明
- 从R调用C++函数并对其进行集成时出错
- 使用QTreeView,如何通过调用函数只突出显示特定的行/列
- 如何在qt中从另一个类调用函数
- 在 COUT 语句中使用 COUT 调用函数
- 如何从线程中的不同模块调用函数?
- C++从函数指针数组调用函数
- 当 A 在 for 循环中调用函数 B 时,如何计算函数 A 的空间复杂度?
- 如何在 C/C++ 中从外部库调用函数
- 如何使用运算符在同一行中多次调用函数
- 是否可以创建一个从不同类调用函数的线程?
- 无法为类成员调用函数
- 如何从另一个标头 c++ 调用函数
- C++有什么方法可以在既不调用函数模板也不提供其模板参数的情况下引用函数模板?
- 如何只允许在调用函数 B 后调用函数 A?
- 我可以这样调用函数吗?
- 如何在 c++ 的类中递归调用函数方法?
- 为什么在指向对象的迭代器上调用函数不允许我更改对象本身?