- 博客(42)
- 收藏
- 关注
原创 C++ & Linux 中 GDB 调试与内存泄漏检测详解
工具/功能GDB 调试Valgrindmtrace核心用途定位崩溃、逻辑错误全面内存检测(泄漏+错误)快速内存检测(泄漏+错误)简单内存泄漏检测编译要求需-g选项无(加-g更好)需需-g选项运行速度接近原程序慢(10-50倍)较快(2-5倍)接近原程序适用场景开发/调试阶段测试阶段开发/测试阶段简单程序/嵌入式环境最佳实践开发 C++ 程序时,编译时加,实时检测内存错误和泄漏。程序崩溃时,开启 core dump,用 GDB 分析core文件定位崩溃点。
2025-12-07 20:38:11
1040
3
原创 lambda表达式中的循环引用问题详解
类中lambda“捕获自己”,本质是捕获指向当前类实例的引用/指针捕获this指针(非shared_ptr管理的类):lambda 持有当前类实例的裸指针(this捕获shared_ptr实例(类继承):lambda 持有当前类实例的强引用(shared_ptr<当前类>lambda 必须被类实例“长期持有”(如作为类的成员变量),才可能形成循环引用。若lambda仅是局部变量(函数内临时创建,不被类持有),即使捕获this,也不会形成循环。避免lambda捕获shared_ptr形成强引用闭环。
2025-12-07 20:32:16
859
原创 单例模式出现多个单例怎么确定初始化顺序?
简单依赖(单向依赖):用「局部静态变量单例」,靠首次访问顺序自动控制。明确依赖(固定顺序):用「显式初始化函数」,在 main 中手动指定顺序。复杂依赖(多向/多层):用「分层初始化」,按层级结构化管理。需解耦/测试:用「依赖注入」,从设计层面消除直接依赖。尽量使用局部静态变量单例,减少单例间依赖,复杂场景补充显式初始化,避免依赖跨编译单元的全局静态单例。C++ 中全局/静态对象的初始化顺序存在“未定义行为”
2025-12-06 21:19:38
957
原创 C++ 内存分配器-allocator
vectorSTL 中负责内存分配的核心是,核心能力是“分离内存分配与对象构造”,为容器提供高效的内存管理。它是所有 STL 容器的默认内存分配器,底层依赖全局,但包装了更灵活的接口。实际开发中,若需优化内存碎片、提升多线程性能,可替换为自定义分配器(如内存池分配器)或 C++17+ 的。STL 内存分配找allocator,核心是“分离分配与构造”。
2025-12-06 21:14:51
1007
原创 C++ 智能指针设计模式详解
核心目标:为一个对象(或资源)提供“包装层”,封装内部实现细节,同时保留原对象的核心接口(或模拟相似接口),并在包装层中添加额外功能(如资源管理、访问控制)。本质:“包装原有对象,增强功能且不改变接口”。核心目标:通过一个“共享计数器”跟踪引用同一资源的对象数量,当计数器为 0 时,自动释放资源(无对象引用该资源)。本质:“共享资源的生命周期管理,通过计数避免重复释放和内存泄漏”。核心目标。
2025-12-06 21:05:02
663
原创 C++ 智能指针底层实现深度解析
自定义删除器的本质是“提供一个可调用对象(函数指针、lambda、函数对象),在析构时调用该对象释放资源”。// 函数指针删除器// 删除器类型擦除为 function// lambda 删除器(捕获变量)// 同样类型擦除特性unique_ptrshared_ptrweak_ptrauto_ptr(已弃用)底层结构裸指针 + 模板删除器(无类型擦除)双指针(数据+控制块)+ 控制块(引用计数+类型擦除删除器)控制块指针(无数据指针)裸指针 + 默认删除器所有权模型。
2025-12-06 21:03:20
1073
原创 Linux - KCP 协议深度解析:原理、与 TCP/UDP 的对比及应用场景
延迟可控:通过nodelayresend等参数,可将延迟优化到接近 UDP 的水平,同时保证可靠性。灵活配置:拥塞控制、重传策略均可关闭/调整,适配不同网络环境(公网/内网/专线)。轻量高效:代码量小,集成成本低,无 TCP 复杂的握手、挥手流程,连接建立/断开延迟低。NAT 穿透友好:基于 UDP,与 UDP 一样容易穿透 NAT 设备(如路由器),适合 P2P 场景。KCP 是一款用户态的快速可靠传输协议,核心价值在于“在 UDP 基础上提供比 TCP 更低的延迟,同时保证可靠性”。
2025-12-03 20:43:35
572
原创 C++ unordered_map 底层实现与详细使用指南
若要使用自定义类型作为的键(Keystd原因:未实现哈希函数或相等比较函数。解决方案:特化std::hash或传入自定义哈希/比较函数(见 1.4 节)。是基于哈希表的无序关联容器,核心优势是平均 O(1) 时间复杂度的查找、插入、删除,是日常开发中高性能键值对存储的首选。
2025-12-03 20:38:11
302
原创 HTTPS 中 TLS 协议详细过程 + 数字证书/签名深度解析
特性TLS 1.2TLS 1.3握手 RTT2 个(Client Hello → Server Hello → Client Finished)1 个(Client Hello → Server 响应 → 应用数据)密钥交换算法支持 RSA、ECDH、DHE 等仅支持 ECDH(强制前向安全)加密套件支持非认证加密(如 AES-CBC)仅支持认证加密(AES-GCM、ChaCha20)会话复用支持会话 ID、会话票据仅支持会话票据(0-RTT 复用)证书验证。
2025-12-03 20:28:48
671
原创 C++ 自定义 String 类
类,可深入理解 C++ 的内存管理、拷贝控制、面向对象设计等核心知识点,同时掌握字符串操作的底层原理,为使用。或其他容器提供理论支撑。
2025-12-02 21:22:34
1295
原创 C++ 设计模式之代理模式详细介绍
代理模式的核心是“透明代理,增强控制”保持接口一致性:代理与真实主题实现相同接口,对客户端透明;组合复用优先:通过持有真实主题的引用/指针,避免继承带来的紧耦合;解决工程问题:重点处理内存管理、线程安全、性能优化(如延迟加载、缓存);避免过度设计:仅在需要控制访问、增强功能或优化性能时使用。
2025-12-02 21:09:28
700
原创 C++ 设计模式之工厂模式详细介绍
由一个单一工厂类负责所有产品的创建,通过传入参数(如类型标识),工厂类动态决定创建哪种具体产品。本质是“集中式创建”,将所有产品的创建逻辑封装在一个工厂中。为解决简单工厂的“开闭原则”问题,将单一工厂拆分为多个具体工厂:每个具体产品对应一个具体工厂,抽象出统一的工厂接口,新增产品时只需新增“具体产品 + 具体工厂”,无需修改现有代码。本质是“分拆式创建”,将创建职责分散到各个具体工厂。当系统中存在多个相关联的产品族。
2025-12-01 16:11:32
996
原创 C++ 设计模式之单例模式详细介绍
唯一性:类的实例在整个程序中只能有一个,禁止外部通过new、拷贝等方式创建多个实例。全局访问:提供一个静态方法(如),让程序任何地方都能便捷访问该实例。可控初始化:根据需求选择“提前初始化”(饿汉式)或“延迟初始化”(懒汉式),平衡资源占用与启动速度。实现方式线程安全(C++11+)延迟初始化代码复杂度内存泄漏风险推荐优先级Meyers 单例(局部静态)是是极低无★★★★★饿汉式(全局静态)是否低无★★★★☆懒汉式(互斥锁)是是中有(需手动销毁)
2025-12-01 16:00:40
1494
原创 C++ 一致性哈希(Consistent Hashing)详细介绍
选择合适的哈希函数(保证分布均匀);用std::map实现高效的哈希环查找;通过虚拟节点解决数据倾斜;考虑线程安全和数据迁移等工程细节。实际开发中,若场景简单(如小规模分布式缓存),可基于本文实现进行修改;若需高性能、高可靠性,建议使用成熟库(如 libconhash、Folly)。不重复造轮子,聚焦业务逻辑,同时理解底层原理以应对问题排查。
2025-12-01 15:54:49
813
原创 C++ 无锁队列(Lock-Free Queue)详细介绍
无锁队列是一种通过原子操作和内存序实现并发安全的数据结构,避免锁竞争带来的性能开销。其核心设计依赖C++的std::atomic和内存序机制,需解决ABA问题、内存回收、虚假共享等难点。常见实现如Michael-Scott队列使用CAS操作和标记指针来保证多线程安全。无锁队列适用于高并发场景,但实现复杂度较高,需谨慎处理线程同步和内存管理问题。
2025-12-01 15:42:52
1207
原创 Linux-内核核心组成部分
Linux内核是操作系统的核心,主要包括五大功能模块:进程管理通过调度程序实现多任务处理;内存管理负责虚拟内存机制;文件系统处理磁盘等存储设备的读写;设备驱动程序管理硬件设备访问;网络管理实现网络通信功能。这些模块协同工作,通过特定接口与CPU、内存、存储设备和网络适配器等硬件交互,为系统提供基础运行环境。
2025-11-30 15:19:38
229
原创 C++线程池-工作窃取式线程池
WorkStealingPool可以设定多个工作线程,每个工作线程都有一个自己的任务队列,每个线程在执行任务时会首先从自己的队列中获取任务,如果自己队列为空,则从其他线程的队列中获取任务。3、高吞吐量任务:WorkStealingPool的工作窃取算法可以减小线程之间的竞争,并且能够在任务队列为空时从其他线程窃取任务,从而减少线程的等待时间,提高整体的任务处理吞吐量。2、递归型任务:对于递归型的任务,workstealingpool能够适应任务的动态变化,根据需要创建和调度子任务,以实现更高效的递归执行。
2025-05-26 22:06:18
540
原创 libevent2-介绍
摘要: Libevent在Windows上通过IOCP实现高性能异步I/O,IOCP基于事件驱动模型,包含I/O端口、完成端口和线程池,适用于高并发网络应用。Libevent解决了网络编程中的痛点:1)提供高效链式缓冲区(evbuffer),减少数据拷贝和系统调用;2)封装底层I/O操作,简化事件驱动编程;3)优化多线程锁机制,确保数据安全。其核心是将Reactor模式封装为事件库,分离I/O检测与操作,支持同步I/O和异步事件处理,适用于网络服务器等场景。
2025-05-25 22:28:41
890
原创 C++线程池-缓存式线程池
本文介绍了缓存式线程池的设计与实现。其核心特点是动态调整线程数量:任务到来时若无空闲线程则创建新线程,空闲线程超时后自动回收。设计上采用同步队列管理任务,通过互斥锁和条件变量实现生产者-消费者模型,并设置任务队列容量限制和超时机制。线程池管理方面,通过线程ID映射表维护线程组,支持动态增减线程,设置最小/最大线程数及空闲超时时间。与固定线程池相比,缓存式更适合处理大量短期高并发任务,能快速响应但需注意任务负载不宜过重。实现时需注意线程安全、资源回收及异常处理等问题。
2025-05-25 06:00:00
705
原创 C++线程池-固定式线程池
本文介绍了固定式线程池的设计与实现。线程池采用三层结构:同步服务层(生产者)、同步队列(缓冲区)和异步服务层(消费者)。同步队列使用C++11的互斥锁、条件变量等技术保证线程安全,并优化了数据获取方式,通过std::move一次性取出所有数据减少锁竞争。线程池类FixedThreadPool封装了线程组管理、任务提交和停止机制,支持可变参数模板的任务添加。测试用例展示了线程池在多线程排序任务中的性能表现,通过高精度计时器测量执行时间。该实现确保了线程安全、任务上限控制和高效的任务处理。
2025-05-24 17:36:12
392
原创 C++-线程池
线程池技术通过预先创建线程和复用机制,有效解决了传统多线程模式中频繁创建销毁线程带来的资源消耗问题。其核心特点包括:控制并发度、任务排队管理、线程复用和负载均衡等。文中介绍了四种典型线程池:固定线程池适用于稳定任务量、缓存线程池适合短时任务、工作窃取线程池实现多核负载均衡、定时线程池用于周期性任务。技术实现采用生产者-消费者模式的三层架构(同步层、队列层、异步层),其中队列层通过同步队列实现任务安全存取,并通过容量控制防止内存溢出。该技术显著提升了系统并发处理能力和资源利用率。
2025-05-24 17:22:39
640
原创 linux-守护进程
每打开一个终端都会产生一个会话,每个会话都以打开的首个进程(bash)作为会话首进程,会话首进程的pid标识该会话,每一个命令都会产生一个进程,进程产生的同时就会产生一个进程组fork后有多个进程,第一个进程是组长,这个组以组长的pid标识。2.守护进程编程流程(主要处理日志信息,让错误直接打印在日志中,并且打印时间):让一个组员进程创建新会话,脱离原有的终端,产生新会话,在新的会话中这个组员的pid就是新会话的sid,同时在新会话中也会产生一个新的组,自己也就是组长进程。
2025-03-06 13:56:56
180
原创 linux-git
1.Git (合并代码,管理版本)是一个分布式版本控制系统,广泛用于软件开发和项目管理。它允许开发者在本地和远程仓库之间同步代码,跟踪代码变更,并管理项目的不同版本。4.远程仓库操作:连接github或gitee(具体命令操作见资料)将多个人的代码联合在一起或交换。分支(Branch):代码的不同版本线,用于开发新功能或修复问题。远程仓库(Remote):存储在服务器上的仓库,用于团队协作。仓库(Repository):存储项目代码和历史记录的地方。提交(Commit):代码的快照,记录了代码的变更。
2025-03-06 00:06:23
215
原创 linux-libevent
1.libevent 是一个库,底层封装了select,poll,epoll,用起来更方便。libevent底层用的是多线程。-->ldd+可执行文件(可以查看用了哪些共享库)libevent提供的事件(编译要加库-levent。
2025-03-05 17:36:27
314
原创 linux-i/o复用-epoll
命令ulimit -n进行查看文件描述符的数量;当要改变文件描述符的数量时变为:ulimit -n 10000,就将文件描述符的数量改为了10000。1.select和poll(LT水平触发模式)收集描述符都是在用户空间进行,所以每次运行都要把描述符拷贝给内核,很麻烦。:仅在文件描述符的状态发生变化时触发事件(如从无数据变为有数据)。在这种模式下,必须读取或写入所有数据,否则可能错过后续事件。:只要文件描述符准备好,就会一直触发事件,直到数据被读取或写入。2.epoll的参数(查AI参数)
2025-03-05 15:19:07
381
原创 linux-io复用-select-poll
int select( int nfds-->检测的描述符的总数目,一般为描述符加一, fd set* readfds-->读事件的集合, fd set* writefds-->写事件的集合, fd set* exceptfds-->异常事件,一般为NULL ,struct timeval*timeout -->超时时间);-->设置 fdset的位fd,将描述符对应的位从0置为1。
2025-03-05 02:55:53
341
原创 linux-mysql
如果一个事务试图插入一个金额为负的订单,那么这个事务会被拒绝,以保持数据库的一致性。2.mysql是c/s(服务器/客户端)结构,有个服务器端和多个客户端,服务器与客户端连接是tcp连接,其中mysql的端口是3306,上述命令安装的是服务器端。(sql语句的集合,这些操作要么都执行,要么都不执行)(一条语句就是一个事物,要执行多条事物语句用begin开始,见资料):例子:转账的例子。:隔离性是指多个事务并发执行时,每个事务都应独立于其他事务,就好像它们是顺序执行的一样。8.视图(有3个问题,见资料)
2025-03-04 22:41:47
979
原创 linux-myhttp实现
SEEK_CUR :读写偏移量将指向当前位置偏移量 + offset 字节位置处, offset 可以为正、也可以为负,如果是正数表示往后偏移,如果是负数则表示往前偏移;4.代码实现简单来说就是:你要访问哪个文件,我在解析文件名,拼接好路径,open在打开它,得到文件大小,组装好报文,再把报头发过去,最后把文件内容发过去。dest :指向目标字符串的指针, src 字符串的内容将被追加到这个字符串的末尾。src :指向源字符串的指针,其内容将被复制到 dest 字符串的末尾。
2024-11-14 21:57:58
333
原创 Linux-udp-http协议-tcp状态转移图
(这里假设客户端先关闭)客户端发送FIN,服务端接收FIN,为第一次挥手,此时服务端变为CLOSE_WAIT,客户端变为FIN_WAIT_1。③recvfrom(int sockfd(套接字描述符),void * buf(传到哪个buff中),size_t len(buff多大),int flags(标志位),struct sockaddr * src_addr(套接字的地址结构-->收到的数据存进去,记录了发送者的IP与端口),socklen_t *addrlen(套接字地址结构大小))-->接收数据。
2024-11-13 05:05:52
1148
原创 Linux-网络-三次握手-四次挥手-多线程并发(线程)
实现多个客户端可以同时连接上服务端,并且可以给服务端发送信息,运用线程的方法,(在上一篇中运用了进程的方法)具体就是将发送信息(send),接收信息(recv),关闭连接(close)放在线程中实现。去重就是当发送数据后,返回的确认报文在路上丢失了,服务端就会认为没有发送过去,就会重新发送,这样就会产生重复的。6.TCP的特点:面向连接(握手,挥手),可靠的(上述保证可靠的三种方法),流式服务(就是一次发送的数据可能被对方多次收到,多次发送的数据可能被对方一次收到,具体见上一篇recv的介绍)
2024-11-12 21:26:19
657
原创 Linux-网络-TCP-客户端-服务端
④accept(int sockfd(监听套接字),struct sockaddr* addr(套接字的地址结构,存放客户端的ip与端口),socklen_t* addrlen(存放客户端套接字的大小))-->接受客户端的连接。①socket(int domain(地址符ipv4/ipv6),int type(服务类型,tcp->流式服务,udp->数据报服务),int protocol(协议版本,目前恒为0))-->创建套接字。⑤close(int fd(监听套接字))-->关闭连接。
2024-11-05 17:48:43
1661
原创 Linux-线程-条件变量 网络基础概念
pthread_cond_init(pthread_cond_t* cond (条件变量的地址) ,const pthread _condattr_t* cond_attr(属性传NULL即可))--->初始化。在linux系统中,线程就是当fork()后产生的子进程与父进程共享内存,地址空间等资源,而且产生的所有子进程都是共享父进程的资源,看起来就是一个进程里面的线程。(1)进程与线程的区别:线程进程内部的一条执行路径(序列),一个进程可以包含多个线程 进程是一个正在运行的程序。
2024-11-03 17:29:58
566
原创 Linux-线程-生产者消费者-读写锁-线程安全
1.问题概述2.图示:1.分为读锁与写锁,可以自行分配,只允许多个读锁可以共同进行,读锁与写锁,写锁与写锁不能同时进行。2. pthread_rwlock_init(pthread_rwlock*restrict rwlock(读写锁地址),const pthread_rwlockattr_t*restrict attr(一般为NULL))-->读写锁初始化。
2024-10-17 14:50:56
775
原创 Linux-线程-信号量-互斥锁
4. int pthread_create(pthread_t *thread(线程id),const pthred_attr_t*attr(线程属性一般不设置,填NULL即可),void*(*start_routine)(void*)(线程函数,有几个线程就创建几个线程函数,参数为void*,返回值为void*的函数指针),void*arg(线程函数的参数))----->创建线程。pthread_mutex_destroy(pthread_mutex_t *mutex(锁变量地址))-->销毁锁。
2024-10-15 17:33:45
790
原创 Linux-进程间通信-共享内存-消息队列
ssize_t msgrcv(int msqid,void*msgp(存放消息的一片空间即结构体),size_t msqsz(存放消息的空间能存多少字节的数据),long msqtyp(哪个类型的消息),int msqflg(标志位,一般为0))//读取消息。msgsnd(int msgid,const void*msgp(消息体),size_t msgsz(数据的大小),int msgflg(标志位,一般为0))//添加消息。5.删除共享内存:ipcrm -m +要删除的共享内存的id号。
2024-10-09 21:16:44
370
原创 Linux-进程间通信-有名管道-无名管道-信号量
open()必须两个进程同时进行,而且必须是一读一写 (管道 满 write阻塞 管道 空 read阻塞)无名管道主要用于父子间进程的通信--->使用接口pipe(int fd[2]) //fd[0]存放读端 fd[1]中存放写端。4.正常创建的文件是在磁盘上存储,速度比较慢,在管道创建文件实际是在内核上,内存调用速度快。半双工-->通信方式可以是A到B也可以是B到A,但在某一时刻只能是一个方向。通信间进程(IPC机制):管道,信号量,共享内存,消息队列,套接字。
2024-10-08 22:42:38
968
原创 linux—信号
二. kill: 发送信号 int kill(pid_t pid,int sig):pid为给哪个进程发,那个进程的id号 sig为给这个进程发什么信号。一. signal:改变信号的响应方式 默认:SIG_IGN 默认:SIG_DFL。信号:通知进程产生了某个事件。
2024-09-19 02:27:25
428
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅