当前位置: 首页 > news >正文

valgrind 单例模式的自动释放(多线程)

单例模式,其中对象是由_pInstance指针来保存的,而在使用单例设计模式的过程中,也难免会遇到内存泄漏的问题。那么是否有一个方法,可以让对象自动释放,而不需要程序员自己手动去释放呢? ——嵌套类

5.1、内存泄漏的检测工具valgrind
安装
sudo apt install valgrind
使用

[外链图片转存中…(img-Onqi9PtX-1728058419413)]

5.2、单例模式自动释放的四种方法 & 多线程
1、友元类

[外链图片转存中…(img-yl7twkoI-1728058419413)]

[外链图片转存中…(img-epIiJsLR-1728058419414)]

#include <iostream>using std::cout;
using std::endl;class Singleton
{friend class AutoRelease;
public:static Singleton *getInstance(){if(nullptr == _pInstance){_pInstance = new Singleton();}return _pInstance;}static void destroy(){if(_pInstance){delete _pInstance;_pInstance =nullptr;}}private:Singleton(){cout << "Singleton()" << endl;}~Singleton(){cout << "~Singleton()" << endl;}
private:static Singleton *_pInstance;
};
Singleton *Singleton::_pInstance = nullptr;class AutoRelease
{
public:AutoRelease(){cout << "AutoRelease()" << endl;}~AutoRelease(){cout << "~AutoRelease()" << endl;if(Singleton::_pInstance){delete Singleton::_pInstance;Singleton::_pInstance =nullptr;}}
};
int main(int argc, char **argv)
{Singleton *ps1 = Singleton::getInstance();AutoRelease ar;//栈对象/* ps1->destroy(); */return 0;
}
2、内部类 + 静态数据成员

[外链图片转存中…(img-oCRKHufV-1728058419414)]

  • 若_ar定义为类成员,则会死锁:
    • new Singleton(),导致_ar在创建的单例堆对象内部,无法使其自动创建&析构(析构自身前,进行delete _pInstance
    • 应将_ar定义为static
    • [外链图片转存中…(img-8lWGqW65-1728058419414)]
#include <iostream>using std::cout;
using std::endl;// 2、内部类 + 静态数据成员class Singleton
{
public:static Singleton *getInstance(){if (_pInstance == nullptr){_pInstance = new Singleton(); // 构造函数// _ar;}return _pInstance;}static void destroy(){if (_pInstance){delete _pInstance;_pInstance = nullptr;}}private:class AutoRelease{public:AutoRelease(){cout << "AutoRelease()" << endl;}~AutoRelease(){cout << "~AutoRelease()" << endl;if (_pInstance){delete _pInstance;_pInstance = nullptr;}}};private:Singleton(){cout << "Singleton()" << endl;}~Singleton(){cout << "~Singleton()" << endl;}private:static Singleton *_pInstance; // 前向声明;定义为static,位于全局静态区(不属于本类!)static AutoRelease _ar; // 前向声明;对象数据成员, _ar不能存在堆上,否则死锁;定义为static,位于全局静态区(不属于本类!)
};Singleton *Singleton::_pInstance = nullptr; // 静态对象必须在类外进行正式声明!
Singleton::AutoRelease Singleton::_ar; // 静态对象必须在类外进行正式声明!int main(int argc, char **argv)
{Singleton *ps1 = Singleton::getInstance();/* Singleton::AutoRelease ar;//栈对象 *//* ps1->destroy(); */return 0;
}/*
AutoRelease()
Singleton()
~AutoRelease()
~Singleton()*/
采用模板
  • Singleton.h
#ifndef __WD_TEMPLATE_SINGLETON_H__
#define __WD_TEMPLATE_SINGLETON_H__#include <iostream>
using std::cout;
using std::endl;
#if 0
class Singleton
{
public:static Point *getInstance(int ix, int iy){if(nullptr == _pInstance) {_pInstance = new Point(ix, iy);_ar;//为了在模板参数推导时创建ar对象}return _pInstance;}
};
#endif
template <class T>
class Singleton
{
public:template <class... Args>static T *getInstance(Args... args){if (nullptr == _pInstance){_pInstance = new T(args...);_ar; // 为了在模板参数推导时创建ar对象}return _pInstance;}private:class AutoRelease{public:AutoRelease(){cout << "AutoRelease()" << endl;}~AutoRelease(){cout << "~AutoRelease()" << endl;if (_pInstance){delete _pInstance;_pInstance = nullptr;}}};private:Singleton(){cout << "Singleton()" << endl;/* _ar; */}~Singleton(){cout << "~Singleton()" << endl;}private:static T *_pInstance;// 前向声明;定义为static,位于全局静态区(不属于本类!)static AutoRelease _ar;// 前向声明;对象数据成员, _ar不能存在堆上,否则死锁;定义为static,位于全局静态区(不属于本类!)
};template <class T>
T *Singleton<T>::_pInstance = nullptr; // 静态对象必须在类外进行正式声明!template <class T>
typename Singleton<T>::AutoRelease Singleton<T>::_ar;  // 静态对象必须在类外进行正式声明! // typename表名是一个类型#endif
  • Test.cpp

    • #include "Singleton.h"#include <iostream>
      using std::cout;
      using std::endl;class Point
      {
      public:Point(int ix = 0, int iy = 0): _ix(ix), _iy(iy){	cout << "Point(int = 0,int = 0)" << endl;	}void print() const{cout << "(" << _ix<< "," << _iy<< ")" << endl;}~Point(){cout << "~Point()" << endl;}private:int _ix;int _iy;
      };int main()
      {Point *pt1 = Singleton<Point>::getInstance(1, 2);Point *pt2 = Singleton<Point>::getInstance(3, 4);pt1->print();pt2->print();cout << "p1 = " << pt1 << endl<< "p2 = " << pt2 << endl;return 0;
      }
3、饿汉模式 + atexit
atexit

[外链图片转存中…(img-M9pmTrsb-1728058419415)]

#include <stdlib.h>
#include <iostream>using std::cout;
using std::endl;void func()
{cout << "void func()" << endl;
}void test()
{atexit(func); // atexit: 进程正常结束时候,注册的func会被执行,注册几次就会执行几次atexit(func);atexit(func);atexit(func);atexit(func);
}int main(int argc, char **argv)
{cout << "start test..." << endl;test();cout << "finish test..." << endl;return 0;
}/*
start test...
finish test...
void func()
void func()
void func()
void func()
void func()*/
饿汉模式 + atexit

[外链图片转存中…(img-tBQqgF0g-1728058419415)]

[外链图片转存中…(img-ruQk952y-1728058419415)]

#include <stdlib.h>
#include <iostream>using std::cout;
using std::endl;// 3、atexit + 饿汉模式class Singleton
{
public:static Singleton *getInstance(){// 在多线程情况下,是不安全的if (_pInstance == nullptr){_pInstance = new Singleton(); // 构造函数atexit(destroy);              // 使用atexit:注册函数destroy一次, 当进程正常结束后,会调用一次注册的函数destroy} else {cout << "_pInstance != nullptr" << endl;}return _pInstance;}static void destroy(){if (_pInstance){delete _pInstance;_pInstance = nullptr;}}private:Singleton(){cout << "Singleton()" << endl;}~Singleton(){cout << "~Singleton()" << endl;}private:static Singleton *_pInstance;
};/* Singleton *Singleton::_pInstance = nullptr; //饱(懒)汉模式, 问题:多线程下,单例模式失效;*/
Singleton *Singleton::_pInstance = getInstance(); // 饿汉模式,可解决多线程不安全问题void *func1(void *arg)
{Singleton::getInstance();
}void *func2(void *arg)
{Singleton::getInstance();
}void *func3(void *arg)
{Singleton::getInstance();
}
int main(int argc, char **argv)
{Singleton *ps1 = Singleton::getInstance();// 饱(懒)汉模式下,多线程不安全;-- 解决:使用饿汉模式// pthread_t th1, th2, th3;// pthread_create(&th1, nullptr, func1, nullptr);// pthread_create(&th2, nullptr, func2, nullptr);// pthread_create(&th3, nullptr, func3, nullptr);return 0;
}
4、多线程场景:pthread_once + atexit

[外链图片转存中…(img-MvIJXvC9-1728058419415)]

#include <pthread.h>
#include <stdlib.h>
#include <iostream>using std::cout;
using std::endl;//4、atexit + pthread_once
//有平台问题,只能在Linux下使用class Singleton
{
public:static Singleton *getInstance(){//当第一个参数是某个固定值的时候,可以保证第一个参数只会被//调用一次  call_oncepthread_once(&_once, init);return _pInstance;}static void init(){_pInstance = new Singleton();//构造函数atexit(destroy);}static void destroy(){if(_pInstance){delete _pInstance;_pInstance = nullptr;}}private:Singleton(){cout << "Singleton()" << endl;}~Singleton(){cout << "~Singleton()" << endl;}
private:static Singleton *_pInstance;static pthread_once_t _once;
};Singleton *Singleton::_pInstance = nullptr; //饱(懒)汉模式
/* Singleton *Singleton::_pInstance = getInstance();//饿汉模式 */
pthread_once_t Singleton::_once = PTHREAD_ONCE_INIT;int main(int argc, char **argv)
{Singleton *ps1 = Singleton::getInstance();return 0;
}

相关文章:

valgrind 单例模式的自动释放(多线程)

单例模式&#xff0c;其中对象是由_pInstance指针来保存的&#xff0c;而在使用单例设计模式的过程中&#xff0c;也难免会遇到内存泄漏的问题。那么是否有一个方法&#xff0c;可以让对象自动释放&#xff0c;而不需要程序员自己手动去释放呢&#xff1f; ——嵌套类 5.1、内…...

OpenFegin

文章目录 一、OpenFegin是什么&#xff1f;二、基本使用三、超时重试机制4.自定义超时重传机制五、底层实现 一、OpenFegin是什么&#xff1f; OpenFeign的全称为Spring Cloud OpenFeign(下文简称OpenFeign),是Spring Cloud团队开发的一款基于 Feign的框架&#xff0c;声明式W…...

LeetCode-2608. 图中的最短环【广度优先搜索 图,腾讯面试真题】

LeetCode-2608. 图中的最短环【广度优先搜索 图&#xff0c;腾讯面试真题】 题目描述&#xff1a;解题思路一&#xff1a;【一图秒懂】枚举起点跑 BFS解题思路二&#xff1a;背诵版解题思路三&#xff1a; 题目描述&#xff1a; 现有一个含 n 个顶点的 双向 图&#xff0c;每个…...

IDEA 编译报错 “java: 常量字符串过长” 的解决办法

目录 一、问题描述二、问题原因2.1 理论角度2.2 源码角度 三、解决方案解决方案①&#xff1a;StringBuilder 拼接解决方案②&#xff1a;读取文件内容 四、方案验证 在线文本换行工具&#xff1a; https://lzltool.cn/Toolkit/WrapWordsInText 一、问题描述 今天在开发过程中…...

RK3568平台开发系列讲解(I2C篇)I2C 总线实现 client 设备方法

🚀返回专栏总目录 文章目录 一、非设备树实现 i2c client1.1、i2c_new_device1.2、i2c client二、设备树实现 i2c2.1、i2c_client 结构体的生成2.2、i2c_driver 驱动2.2.1、module_i2c_driver2.2.2、fan53555_regulator_probe沉淀、分享、成长,让自己和他人都能有所收获!�…...

K8S安装和部署

环境部署说明 主机IPmaster172.25.254.100node10172.25.254.10node20172.25.254.20harbor172.25.254.233 所有节点禁用selinux和防火墙 所有节点同步时间和解析 所有节点安装docker-ce 所有节点禁用swap&#xff0c;注意注释掉/etc/fstab文件中的定义 解析配置&#xff08;…...

Singleton(单例模式)

1. 意图 在开发中&#xff0c;若某些模块或功能只需要一个类实例&#xff0c;所有调用地方通过着一个类对象访问功能&#xff0c;单例模式符合这种类实例创建模式&#xff0c;并且通过提供统一类实例接口访问类对象。 2. 适用性 《Gof 设计模式-可复用面向对象软件的基础》中对…...

【Linux报错】“-bash: cd: too many arguments“

问题描述 今天使用 cd 想要调整某个文件目录时&#xff0c;发现以下报错 原因分析&#xff1a; arguments 是参数的意思&#xff0c;该报错提示参数过多&#xff0c;意味着系统识别到了多余参数 本质原因&#xff1a;你的命令中输入了多余的 ”空格“ &#xff0c;检查一…...

C# WebService返回参数为DataTable报错“XML文档有错误”

该问题由于DataTable列存在自定义类型。 解决该报错需要以下几步&#xff1a; 1、自定义类型增加xml序列化 2、由于C#从 XML 反序列化 DataSet 或 DataTable 时的默认限制&#xff0c;所以需要先把调用方的项目开放限制&#xff0c;如果是.netframework项目&#xff0c;需要…...

[paddle]paddleseg快速开始

快速开始 为了让大家快速了解PaddleSeg&#xff0c;本文档使用一个简单示例进行演示。在实际业务中&#xff0c;建议大家根据实际情况进行调整适配。 在开始下面示例之前&#xff0c;请大家确保已经安装好PaddleSeg开发环境&#xff08;安装说明&#xff09;。 1 准备数据 …...

UNIAPP popper气泡弹层【unibest框架下】vue3+typescript

看了下市场的代码&#xff0c;要么写的不怎么好&#xff0c;要么过于复杂。于是把市场的代码下下来了自己改。200行代码撸了个弹出层组件。兼容H5和APP。 功能&#xff1a; 1)只支持上下左右4个方向的弹层不支持侧边靠齐 2)不对屏幕边界适配 3)支持弹层外边点击自动隐藏 4)支持…...

launcher.py: error: the following arguments are required: --output_dir

记录一个LLaMA-Factroy配置过程。 安装 git clone --depth 1 https://github.com/hiyouga/LLaMA-Factory.git cd LLaMA-Factory pip install -e ".[torch,metrics]"训练 CUDA_VISIBLE_DEVICES0 llamafactory-cli train example/train_lora/.yaml按理说配置好文件应…...

C语言基础之结构体

今天我们来讲讲C语言基础的最后一个知识点了 —— 结构体。不知道大家对前面的C语言基础的知识点掌握的怎么样了呢&#xff1f;下面我们就开始讲解结构体的相关知识点吧&#xff01; 什么是结构体呢&#xff1f;或者说结构体有什么作用呢&#xff1f;对于复杂对象来说&#xff…...

Redis入门第四步:Redis发布与订阅

欢迎继续跟随《Redis新手指南&#xff1a;从入门到精通》专栏的步伐&#xff01;在本文中&#xff0c;我们将深入探讨Redis的发布与订阅&#xff08;Pub/Sub&#xff09;模式。这是一种强大的消息传递机制&#xff0c;适用于各种实时通信场景&#xff0c;如聊天应用、实时通知和…...

MySQL 之权限与授权

MySQL 权限及授权系统用于控制数据库用户对数据库资源的访问和操作权限。它提供了一种细粒度的安全控制机制&#xff0c;确保只有被授权的用户才能执行特定的操作。MySQL 的权限控制体系非常灵活&#xff0c;支持多种权限类型及级别&#xff08;数据库、表、列、存储过程等&…...

解决方案:Pandas里面的loc跟iloc,有什么区别

文章目录 一、现象二、解决方案案例使用loc使用iloc 简单总结 一、现象 在用Pandas库处理数据的时候&#xff0c;久而久之不用loc跟iloc&#xff0c;难免会有些混乱记混 二、解决方案 在Pandas中&#xff0c;loc和iloc是两种常用的数据选择方法&#xff0c;它们的主要区别在…...

C# 和 C++ 混合编程

以下是一个关于 C# 和 C 混合编程 的教程详细目录&#xff0c;涵盖了混合编程中的各个重要方面&#xff1a; 目录 1. 引言 1.1 什么是混合编程&#xff1f; 1.2 为什么选择 C# 和 C 进行混合编程&#xff1f; 1.3 应用场景和优势 2. 基本概念 2.1 C# 和 C 的基础差异 2.…...

Vxe UI vue vxe-table 实现表格单元格选中功能

Vxe UI vue vxe-table 实现表格单元格选中功能 在表格中实现鼠标点击任意单元格&#xff0c;选取的功能&#xff0c;通过 mouse-config 配置就可以开启单选功能&#xff0c;多选单元格选取功能需安装插件支持。 代码 参数说明 mouse-config 鼠标配置项&#xff1a; selected&…...

组合模式详解

1、组合模式基本介绍 1) 组合模式&#xff08;Composite Pattern&#xff09;&#xff0c;又叫部分整体模式&#xff0c;它创建了对象组的树形结构&#xff0c;将对象组合成树状结构以 表示“整体-部分”的层次关系。 2) 组合模式依据树形结构来组合对象&#xff0c;用来表示部…...

AltiumDesigner脚本开发-DIP封装制作

1.点击工具栏的运行工具(蓝色向右三角图标)可以执行脚本程序&#xff1b; 2.点击菜单栏Run->Run可以执行脚本程序&#xff1b; 3.在脚本编辑器中&#xff0c;按键盘的F9键可以执行脚本程序&#xff1b; 4.通过菜单栏执行脚本程序&#xff08;需要将程序添加到菜单栏中&am…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...