c++ lambda捕获this 导致多线程下类释放后还在使用的错误问题

 更新时间:2023年02月03日 11:03:13   作者:大老虎打老虎  
Lambda表达式是现代C++的一个语法糖,挺好用的。但是如果使用不当,会导致内存泄露或潜在的崩溃问题,这里总结下c++ lambda捕获this 导致多线程下类释放后还在使用的错误问题,感兴趣的朋友一起看看吧

Lambda介绍

“Lambda表达式是现代C++在C ++ 11和更高版本中的一个新的语法糖 ,在C++11、C++14、C++17和C++20中Lambda表达的内容还在不断更新。 lambda表达式(也称为lambda函数)是在调用或作为函数参数传递的位置处定义匿名函数对象的便捷方法。通常,lambda用于封装传递给算法或异步方法的几行代码 。

c++的lambda 可以捕获this指针,使lambda可以在自定义的function内使用类的成员函数,这是因为捕获this后隐式的在成员变量前加了this

但是需要注意的是,这里捕获this,不是以一种拷贝的方式,更像是一种引用(或者别名,描述可能不准确),当在外面这个类的生命周期结束时,lambda内部还在调用这个类的成员函数,那么就会出错

我遇到的问题是 捕获了类A的this,对A的一个shared_ptr进行操作。偶然会出现shared_ptr的内部基类spt_count_base的报错。看了下这个shared_ptr 的use_count和weak_count都是0,

这就非常奇怪。shared_ptr计数是线程安全的,(但是实际指向对象和计数不是原子操作),并且访问这个sptr也加了锁,为什么会出现被释放了的情况。

大概再说下情景

class A

{
  shared_ptr<B> sptr;

  sptr.func = [this](){ do something};

}
class B

{
  shared_ptr<map> sptrMap;

  func()

  {

      //概率崩溃
             sptrMap.erase();

  }
}

当A被析构后,B注册的回调被另一个线程调用了func();这时可能会出现A开始析构,刚好析构到B,并且B的sptrMap已经析构时,出现崩溃。但这个顺序不是确定的无法保证,所以也不一定必出现这种现象。

防止这种现象可以加个判断,在sptrMAp不为空时不进行析构。或者用weak_ptr.在捕获this前,用 weak_ptr p = std::shared_from_this;然后在lambda最开始用p.lock判断A是否释放

通过这个了解到了lambda捕获的一个坑,及类析构的顺序及析构时线程安全的保护

另附实际代码

using namespace std;
struct Foo {
  std::unique_ptr<int> p;
  std::function<void()> f() {
    p.reset(new int(1));
    return [=] { cout << *p << endl; };
  }
};

int main() {
  auto foo = new Foo();
  auto f = foo->f();
  delete foo;
  f();
}

运行结果为0而非1,而且这里输出0是未定义行为,因为访问的实际上是被回收的空间,只是因为编译器的delete并没有对回收的空间做额外的操作,所以p指向的仍然是原来那块,只不过那块已经被unique_ptr的析构函数自动清除了,只不过将清除的部分全部置为0而已。

到此这篇关于c++ lambda捕获this 导致多线程下类释放后还在使用的错误的文章就介绍到这了,更多相关c++ lambda捕获this内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言中无符号与有符号及相加问题

    C语言中无符号与有符号及相加问题

    这篇文章主要介绍了C语言中无符号与有符号及相加问题,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-08-08
  • 基于C语言实现简单的12306火车售票系统

    基于C语言实现简单的12306火车售票系统

    火车售票系统给我们的出行带来了极大的方面,那么他基于编程是如何实现的呢?今天小编抽时间给大家分享一个使用C语言写的一个简单的火车票系统,感兴趣的朋友参考下
    2016-09-09
  • C++设计模式之享元模式

    C++设计模式之享元模式

    这篇文章主要介绍了C++设计模式之享元模式,本文讲解了什么是享元模式、享元模式代码实例、享元模式的优点等内容,需要的朋友可以参考下
    2014-10-10
  • 深入理解C++之策略模式

    深入理解C++之策略模式

    下面小编就为大家带来一篇深入理解C++之策略模式。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-06-06
  • C语言实现简单学生学籍管理系统

    C语言实现简单学生学籍管理系统

    这篇文章主要为大家详细介绍了C语言实现简单学生学籍管理系统,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • C++扫雷游戏的简单制作

    C++扫雷游戏的简单制作

    这篇文章主要为大家详细介绍了C++扫雷游戏的简单制作,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • C语言中fchdir()函数和rewinddir()函数的使用详解

    C语言中fchdir()函数和rewinddir()函数的使用详解

    这篇文章主要介绍了C语言中fchdir()函数和rewinddir()函数的使用详解,是C语言入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • C语言实现扫雷小游戏的示例代码

    C语言实现扫雷小游戏的示例代码

    这篇文中主要为大家详细介绍了如何利用C语言实现经典的扫雷小游戏。扫雷小游戏主要是利用字符数组、循环语句和函数实现,感兴趣的小伙伴可以了解一下
    2022-10-10
  • OpenCV实现高斯噪声

    OpenCV实现高斯噪声

    这篇文章主要为大家详细介绍了OpenCV实现高斯噪声,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • C++ 自由存储区是否等价于堆你知道吗

    C++ 自由存储区是否等价于堆你知道吗

    自由存储是C++中通过new与delete动态分配和释放对象的抽象概念,而堆(heap)是C语言和操作系统的术语,是操作系统维护的一块动态分配内存
    2021-08-08

最新评论