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++中不能重载为友元函数的四个运算符进行了详细的分析介绍,需要的朋友可以过来参考下
    2013-07-07
  • C++迭代器iterator详解

    C++迭代器iterator详解

    这篇文章主要为大家详细介绍了C++迭代器模式Iterator,具有一定的参考价值,感兴趣的小伙伴们可以参考一下希望能给你带来帮助
    2021-08-08
  • C语言中魔性的float浮点数精度问题

    C语言中魔性的float浮点数精度问题

    这篇文章主要介绍了魔性的float浮点数精度问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • 对C++默认构造函数的一点重要说明

    对C++默认构造函数的一点重要说明

    下面小编就为大家带来一篇对C++默认构造函数的一点重要说明。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • Qt使用QCamera实现切换相机,分辨率和图像捕获功能

    Qt使用QCamera实现切换相机,分辨率和图像捕获功能

    这篇文章主要为大家介绍了如何利用Qt中的相机类QCamera,取景器类QCameraViewfinder,图像捕获类QCameraImageCapture实现切换相机、分辨率和图像捕获功能,需要的可以了解一下
    2023-04-04
  • c++ 智能指针基础详解

    c++ 智能指针基础详解

    这篇文章主要介绍了c++ 智能指针基础的相关资料,帮助大家更好的理解和学习使用c++,感兴趣的朋友可以了解下
    2021-02-02
  • C++ new/delete相关知识点详细解析

    C++ new/delete相关知识点详细解析

    C语言用一堆标准库函数malloc和free在自由存储区中分配存储空间,而C++则用new和delete表达式实现相同的功能
    2013-09-09
  • C语言 模拟实现memcpy与memmove函数详解

    C语言 模拟实现memcpy与memmove函数详解

    这篇文章主要介绍了C语言详解如何模拟内存函数,用到了mencpy与memmove两个函数,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-04-04
  • C++、Qt分别读写xml文件的方法实例

    C++、Qt分别读写xml文件的方法实例

    Qt提供了QDomElement 类用于完成对xml文件的读取和写入,这篇文章主要给大家介绍了关于C++、Qt分别读写xml文件的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-03-03
  • C++实现大数乘法算法代码

    C++实现大数乘法算法代码

    这篇文章主要介绍了C++实现大数乘法算法代码的相关资料,需要的朋友可以参考下
    2015-03-03

最新评论