- 主题:lambd表达式对已析构对象为啥不抛异常
把对象捕获绑定在lambda表达式里,对象已经析构了,在调用lambda时不抛异常,按UB处理,这是大坑啊。
我发现对这种情况,只能用 enable_share_from_this 来搞,把对象指针shared_ptr<T>托管到队列或者数组里,异步适时再调用该对象的成员函数。 (我的场景:每个算法对象订阅行情,并在收行情数据后调度器按每个股票快照 调用每个算法对象的onMarketDepth(const MarketDepth& md),这里面就涉及每次调度时,算法对象算法是否还存活)
#include <iostream>
#include <memory>
#include <thread>
#include <vector>
#include <functional>
class MyClass {
public:
MyClass(int i):m(i) {
std::cout << "----MyClass::MyClass() " << m << std::endl;
}
void member_function() {
std::cout << "****I am still alive! " << m << std::endl;
}
~MyClass() {
std::cout << "----MyClass::~MyClass() " << m << std::endl;
}
int m;
};
int main() {
std::vector<std::function<void()>> v_f;
{
for (auto& i : { 2,4,6 }) {
std::shared_ptr<MyClass> my_class = std::make_shared<MyClass>(i);
auto lambda = [my_class]() {
my_class->member_function();
};
std::cout << i << " lambda name() = " << typeid(lambda).name() << std::endl;
std::cout << i << " lambda.address() = " << &lambda << std::endl;
v_f.push_back(lambda);
}
}
{
for (auto& i : { 1,3,5}) {
MyClass my_class{i};
auto lambda = [&my_class]() {
my_class.member_function();
};
std::cout << i << " lambda name() = " << typeid(lambda).name() << std::endl;
std::cout << i << " lambda address() = " << &lambda << std::endl;
v_f.push_back(lambda);
}
}
for (auto& task : v_f) { // 1 3 5 已经析构了,居然还能跑, 最后一个数据还正确.... 这隐藏坑
task();
}
return 0;
}
--
FROM 113.91.210.*
还有如果lambda这里传的智能指针 的引用,一样要废。 结果还跑得很high,如果是测试环境开发,对数据没仔细,完全无声不报错还以为 正确呢
std::shared_ptr<MyClass> my_class = std::make_shared<MyClass>(i);
auto lambda = [&my_class]() {
my_class->member_function();
};
--
FROM 113.91.210.*
下面的也能跑。结果还是“对”的。
闭包里保存引用和指针得万分小心
#include <iostream>
#include <memory>
#include <vector>
#include <functional>
class MyClass {
public:
MyClass(int i):m(i) {
std::cout << "----MyClass::MyClass() " << m << std::endl;
}
void member_function() {
std::cout << "****I am still alive! " << m << std::endl;
}
~MyClass() {
std::cout << "----MyClass::~MyClass() " << m << std::endl;
}
int m;
};
int main() {
std::vector<std::function<void()>> v_f;
int* p = new int[100];
{
for (auto& i : { 10}) {
MyClass my_class{i};
auto lambda = [&my_class,p,i]() {
my_class.member_function();
p[i] = i;
};
std::cout << i << " lambda name() = " << typeid(lambda).name() << std::endl;
std::cout << i << " lambda address() = " << &lambda << std::endl;
v_f.push_back(lambda);
}
}
std::cout << "******************" << std::endl;
delete[] p;
for (auto& task : v_f) {
task();
}
std::cout << p[10] << std::endl;
return 0;
}【 在 MyWorkLife 的大作中提到: 】
: 你这个例子正好说明问题
: 不像前面例子里面c++ lambda引用一个已经析构的空悬对象
: python对于保持对象生存周期毫无压力
: ...................
--
FROM 113.91.210.*