C/C++
文章平均质量分 66
C/C++
birate_小小人生
专注,自信,坚持
展开
-
GoogleTest
文章目录1. 一个好的测试2. 环境准备3 断言后台服务器:后台开发视频1. 一个好的测试测试应该是独立的和可重复的。调试一个由于其他测试而成功或失败的测试是一件痛苦的事情。googletest通过在不同的对象上运行测试来隔离测试。当测试失败时,googletest允许您单独运行它以快速调试。测试应该很好地“组织”,并反映出测试代码的结构。googletest将相关测试分组到可以共享数据和子例程的测试套件中。这种通用模式很容易识别,并使测试易于维护。当人们切换项目并开始在新的代码库上工原创 2022-05-22 21:01:25 · 273 阅读 · 1 评论 -
CMake
CMake文章目录CMake1. 最简单的CMake2. 添加message信息3. 添加链接库4. 链接第三方库5. 变量与缓存6. 跨平台和编译器7. 分支和判断8. 变量和作用域我们使用的cmake版本为3.x 以上。首先我们熟悉基本的命令:cmake -B build // 在源码目录用 -B 直接创建 build 目录并生成 build/Makefilecmake --build build -j4原创 2022-04-30 14:41:26 · 4231 阅读 · 0 评论 -
死锁的检测与实现
死锁的发生是由于线程间资源争夺引起的,这里不对线程的死锁的概念和原理解释。主要介绍死锁的检测和具体实现,检测我们可以使用一个有向图来表示, 线程 A 获取线程 B 已占用的锁,则为线程 A 指向线程 B。 如何为线程 B 已占用的锁?运行过程线程 B 获取成功的锁。检测的原理采用另一个线程定时对图进程检测是否有环的存在。数据结构定义:typedef enum { PROCESS, RESOURCE} Type; // 定义资源的类型typedef struct source_type_t { /原创 2022-04-10 11:33:33 · 1711 阅读 · 1 评论 -
自己动手实现一个进程间通信组件
文章目录背景原理代码实现背景我们知道linux的进程的间通信的组件有管道,消息队列,socket, 信号量,共享内存等。但是我们如果自己实现一套进程间通信的机制的话,要怎么做?了解android 开发的可能会知道,android里面有个binder机制,简单来说,就是一个进程往binder里面写数据,另一个进程从binder里面读出数据。所以我们也可以按照binder的思路来设计一个自己的进程间通信组件。原理我们的设计思路很简单,我们首先需要注册一个字符设备文件叫**/dev/channel*原创 2022-03-27 22:08:26 · 1132 阅读 · 0 评论 -
gdb的常用命令
命令名称命令缩写说明runr运行程序continuec让暂停的程序继续运行breakb添加断点tbreaktb添加临时断点backtracebt查看当前线程的调用堆栈framef切换到当前调用线程的指定堆栈infoinfo查看断点、线程等信息enableenable启动某个断点disabledisable禁用某个断点deletedel删除断点listl显示源码printp打...原创 2021-10-17 17:19:45 · 182 阅读 · 0 评论 -
排序算法
#include <stdio.h>#include <stdlib.h>#include "malloc.h"void Swap(int A[],int i,int j){ int temp; temp=A[i]; A[i]=A[j]; A[j]=temp;}void BubbleSort(int A[],int n)//冒泡...原创 2018-07-24 14:12:44 · 114 阅读 · 0 评论 -
引导内存分配器原理
文章目录引导内存分配器原理a. bootmem分配器b.memblock分配器引导内存分配器原理参考视频链接 https://ke.qq.com/course/417774?flowToken=1040955a. bootmem分配器在启动过程期间,尽管内存管理尚未初始化,但内核仍然需要分配内存以创建各种数据结构。bootmem分配器用于在启动阶段早期分配内存。显然,对该分配器的需求集中于简单性方面,而不是性能和通用性。因此内核开发者决定实现一个最先适配( first-fit)分配器用于在启动阶原创 2021-12-12 16:57:50 · 590 阅读 · 0 评论 -
int (*a)[10] 和 int *a[10] 的区别
首先,int *a[10] : 是数组指针,本质上就是数组元素是是个int型指针的一维数组, int (*a)[10] : a是指针,指向一个数组。此数组有10个int型元素int (*a)[10]与int*a[10]的差别就在那个小括号int *a[10]先找到声明符a,然后向右看,有[ ]说明a是个数组,再向左看,是int *,说明数组中的每个元素是int *。所以这是一个存放i...转载 2018-05-17 11:17:50 · 10026 阅读 · 4 评论 -
池式结构--内存池
文章目录内存管理伙伴算法slab算法内存池的实现1. 分配2. 释放3. 扩容内存管理我们经常在堆上进行内存的分配和释放时,就会产生内存碎片问题。内部碎片的产生:因为所有的内存分配必须起始于可被 4、8 或 16 整除(视 处理器体系结构而定)的地址或者因为MMU的分页机制的限制,决定内存分配算法仅能把预定大小的内存块分配给客户。假设当某个客户请求一个 43 字节的内存块时,因为没有适合大小的内存,所以它可能会获得 44字节、48字节等稍大一点的字节,因此由所需大小四舍五入而产生的多余空间就叫内部碎原创 2021-08-08 23:42:18 · 325 阅读 · 0 评论 -
栈的应用一:
如何实现编译器中的符号成对检测?解决方案算法思路 从第一个字符开始扫描 当遇见普通字符时忽略,当遇见左符号时压入栈 当遇见右符号时从栈中弹出栈顶符号 进行匹配• 匹配成功:继续读入下一个字符• 匹配失败:立即停止,并报错 结束:• 成功: 所有字符扫描完毕,且栈为空• 失败:匹配失败或所有字符扫描完毕但栈非空 int isLeft(char c){ int ret = 0; s...原创 2018-05-09 21:09:51 · 150 阅读 · 0 评论 -
数组指针和指针数组的区别
数组指针(也称行指针)定义 int (*p)[n];()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。如要将二维数组赋给一指针,应这样赋值:int a[3][4];int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。 p=a; //将该二...转载 2018-09-14 09:00:17 · 110 阅读 · 0 评论 -
野指针
野指针 概念野指针通常是因为指针变量中保存的值不是一个合法的内存地址而造成的。 野指针不是NULL指针,是指向不可用内存的指针。 NULL指针不容易用错,因为if语句很好判断一个指针是不是NULL。C语言中没有任何手段可以判断一个指针是否为野指针!野指针产生原因1、局部指针变量没有被初始化指针变量指向的地址值不清楚,没有初始化,这时候对这个地址处的内存写入数据,就可能出错。2、使用已经释放过后的指...原创 2018-05-19 17:54:22 · 297 阅读 · 0 评论 -
池式结构--异步池
异步和同步的区别就是可以不需要一直等待IO,有结果就返回数据。异步池主要关注以下几点:具有多个连接使用网络io的基础,发送对应的协议多个连接,发送完请求之后,fd使用epoll去管理。请求与相应的线程,不能放到一个线程去处理。异步池可以分以下思路进行处理:1. commit: 请求* 建立网络连接* 组织好对应的协议,如dns* 发送到对应的服务器* fd是否可读,fd加入epollint dns_async_client_commit(struct async_context原创 2021-04-05 16:55:40 · 180 阅读 · 0 评论 -
定时器系列2 -最小堆
概念满二叉树: 所有的层节点数都是该层所能容纳节点的最⼤数量(满足 2n2^n2n; n>=0n > =0n>=0) ;完全二叉树: 若⼆叉树的深度为 h ,除了 h 层外,其他层的节点数都是该层所能容纳节点的最⼤数量(满⾜ ),且 h 层都集中在最左侧;最小堆:是一颗完全二叉树;某一个节点的值总是小于等于它的子节点的值;堆中每个节点的子树都是最小堆;增加操作为了满⾜完全⼆叉树定义,往⼆叉树最⾼层沿着最左侧添加⼀个节点;然后考虑是否能上升操作;如果此时添加值为 4 的原创 2021-10-10 18:52:19 · 348 阅读 · 0 评论 -
池式结构-线程池
文章目录任务队列执行队列管理组件创建线程池线程运行任务回调函数在多线程的操作中,我们经常使用线程池来进行大量的计算、缓存磁盘、写log等。线程池主要由任务队列、执行队列和管理组件。三部分组成。如图,中间的框框就是我们的线程池,threadqueue负责从taskqueue取任务,当没有任务时,thread通过条件变量进行等待。处理完成之后,返回处理的结果。任务队列typedef struct job { void (*func)(struct job *arg); void *us原创 2021-07-04 21:58:36 · 243 阅读 · 0 评论 -
定时器系列1-红黑树
对于服务端来说,驱动服务端逻辑的事件主要有两个,⼀个是⽹络事件,另⼀个是时间事件;在不同框架中,这两种事件有不同的实现⽅式;第⼀种,⽹络事件和时间事件在⼀个线程当中配合使⽤;例如nginx、 redis;// 第⼀种while (!quit) {int now = get_now_time();// 单位: msint timeout = get_nearest_timer() - now;if (timeout < 0) timeout = 0;int nevent = epoll_原创 2021-09-15 22:29:21 · 267 阅读 · 0 评论 -
Linux中的时间函数
Linux 中常用的函数有以下函数 sleep、usleep、ndelay、udelay、mdelay 等Linux 系统编程下用到的延时函数在头文件“#include <unistd.h>”中,包括函数 sleep、usleep。Linux 内核中用到的延时函数在“#include <linux/delay.h>”中,包括函数 ndelay、udelay、mdelay...原创 2018-11-28 18:18:33 · 788 阅读 · 0 评论 -
嵌入式几种操作
C语言位操作中指定的某一位数置0、置1、取反一、指定的某一位数置1 宏 #define setbit(x,y) x|=(1<<y)二、指定的某一位数置0 宏 #define clrbit(x,y) x&=~(1<<y)三、指定的某一位数取反 宏 #define reversebit(x,...转载 2019-04-09 09:34:48 · 555 阅读 · 0 评论 -
const, volatile同时修饰一个变量
文章基础: (1) “编译器一般不为const变量分配内存,而是将它保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作。” (2) volatile的作用是“告诉编译器,i是随时可能发生变化的,每次使用它的时候必须从内存中取出i的值”。 ...转载 2018-05-05 11:16:59 · 410 阅读 · 0 评论 -
volatile变量
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 1). 并行设备的硬件寄存器(如:状态寄存器) 2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variabl...转载 2018-07-13 16:54:17 · 173 阅读 · 0 评论 -
红黑树的系列文章
最近看到一篇写的很详细的红黑树的系列文章:红黑树(一)之 原理和算法详细介绍红黑树(二)之 C语言的实现红黑树(三)之 Linux内核中红黑树的经典实现红黑树(四)之 C++的实现转载 2021-09-12 17:33:54 · 77 阅读 · 0 评论 -
Linux 检测内存泄漏
内存泄漏是指由于疏忽或错误造成程序未能释放已经不再使用的内存。 内存泄漏并非指内存在物理上的消失, 而是应用程序分配某段内存后, 由于设计错误, 导致在释放该段内存之前就失去了对该段内存的控制, 从而造成了内存的浪费。我们平时开发过程中不可避免的会遇到内存泄漏问题,经常使用下面几个工具。valgrindmtracedmallocccmallocmemwatchdebug_new这里我看到过一个新的一个排查内存泄漏的工具: AddressSanitizer(ASan), 该工具为 gcc原创 2021-08-22 23:37:41 · 373 阅读 · 0 评论 -
协程的hook操作
文章目录1. hook 原理1.1 函数解析2. hook实现2.1 使用环境变量LD_PRELOAD2.2 源码入侵1. hook 原理hook机制本质上是一种函数的劫持技术,比如我们通常需要调用malloc函数来进行内存分配,那么能不能我们自己封装一个同名、同入参和同返回值的malloc函数来替代系统的malloc函数,在我们自己封装的malloc函数中实现一些特定的功能,而且也能回调系统的malloc,这就是hook机制。系统提供给我们的dlopen、dlsym族函数可以用来操作动态链接库,比如原创 2021-07-12 00:00:36 · 773 阅读 · 0 评论 -
c++ 11的using
在c++11中我们可以使用using定义别名,例如:我们定义一个模板,使用usingtemplate<typename T>using vec = std::vector<int MyAlloc<int>>;//使用vec<int> coll; //等同于std::vector<int MyAlloc<int>> coll;我们使用#define 或者 typedef 试试;#define Vec<T>原创 2021-05-30 17:05:33 · 256 阅读 · 0 评论 -
c++11的=delete,=default
文章目录1. default2. delete1. defaultC++11允许添加“=default”说明符到函数声明的末尾,以将该函数声明为显示默认构造函数。这就使得编译器为显示默认函数生成了默认实现,它比手动编程函数更加有效。例如,每当我们声明一个有参构造函数时,编译器就不会创建默认构造函数。在这种情况下,我们可以使用default说明符来创建默认说明符。以下代码演示了如何创建:// use of defaulted functions#include <iostream>us原创 2021-05-29 23:17:41 · 127 阅读 · 0 评论 -
c++深拷贝(两种)和浅拷贝
文章目录1.深拷贝和浅拷贝2. 移动构造函数(std::move())3.左值和右值c++的拷贝有两种:即深拷贝和浅拷贝.1.深拷贝和浅拷贝在未定义显示拷贝构造函数的情况下,系统会调用默认的拷贝函数——即浅拷贝,它能够完成成员的一一复制。当数据成员中没有指针时,浅拷贝是可行的;但当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象快结束时,会调用两次析构函数,而导致指针悬挂现象,所以,此时,必须采用深拷贝。深拷贝与浅拷贝的区别就在于深拷贝会在堆内存中另外申请空间来原创 2021-05-29 12:03:32 · 8044 阅读 · 1 评论 -
c++11 Initializate
erere原创 2021-05-26 23:59:57 · 408 阅读 · 0 评论 -
C++11~14 Variadic tempates(可变的参数模板)
在写代码中,我们经常会碰到 … 这样的一个参数,这个其实就是可变参数的意思,有时候我们不确定需要多少个参数,我们就会用…,经常在print函数中使用,例如:int printf(const char *fmt, ...) { int i; char buf[256]; va_list arg = (va_list)((char*)(&fmt) + 4); i = vsprintf(buf, fmt, arg); write(buf, i)原创 2021-05-23 23:53:55 · 226 阅读 · 0 评论 -
无锁队列
先贴上一个大佬的blog,讲的比较好:无锁队列CAS⽐较并交换(compare and swap, CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作,从⽽避免多线程同时改写某⼀数据时由于执⾏顺序不确定性以及中断的不可预知性产⽣的数据不⼀致问题。 该操作通过将内存中的值与指定数据进⾏⽐较,当数值⼀样时将内存中的数据替换为新的值。CAS是所有CPU指令都支持CAS的原子操作(X86中CMPXCHG汇编指令),用于实现实现各种无锁(lock free)数据结构。bool c原创 2021-04-18 20:55:34 · 1071 阅读 · 0 评论 -
取余操作转换为位操作
我们一般取余的操作为 M%N;在编译器会把操作转化为:M % N = M -N * floor(M/N);此时,我们可以将N替换为 2^K,这里 2^K 恰好大于N,这样M % 2^K 就可以转换为 M & (2^K -1)例如: unsigned int i = 5, j = 8; printf("%d\n", i%j); printf("%d\n", i&(j-1));...原创 2021-04-12 22:34:16 · 964 阅读 · 0 评论 -
用宏定义字节对齐
摘自: https://blog.csdn.net/reille/article/details/6329195页面对齐相关的宏(详解):https://blog.csdn.net/I_feige/article/details/60962935计算a以size为倍数的上下界数:#define alignment_down(a, size) (a & (~(size-1)) )#define alignment_up(a, size) ((a+size-1) & (~ (size转载 2021-04-12 22:15:14 · 1256 阅读 · 0 评论 -
锁
互斥锁自旋锁读写锁原子操作原创 2021-04-11 00:06:29 · 250 阅读 · 0 评论 -
谈谈 单例模式
单例模式单例模式是最简单的一种设计模式,保证⼀个类仅有⼀个实例,并提供⼀个该实例的全局访问点。class Singleton{public:static Singleton * GetInstance{ if(instance == NULL) instance = new Singleton(); return instance;}private:Singleton(){} //构造Singleton(const Singleton&){} //拷贝构造Singl原创 2021-01-24 23:51:34 · 106 阅读 · 1 评论 -
查找与排序-KMP算法
C++常用的排序算法:冒泡排序void BubbleSort(int *a,int len){ int temp; for(int i=0; i<len; ++i){ for(int j=0; j<len-i-1; ++j){ if(a[j]>a[j+1]){ temp =a[j]; a[j] = a[j+1]; a[j+1] =原创 2020-12-16 23:15:52 · 181 阅读 · 0 评论 -
TCP/IP 第二篇 Sample code
TCP网络编程API 在网络中进程间如何通信呢?TCP/IP协议族已经帮我们解决了这个问题,网络层的IP地址可以唯一表示网络中的主机,而传输层的"协议+端口"可以唯一标识主机中的应用程序(进程)。这样利用三元组(IP地址,协议,端口)就可以标识网络的进程了,网络中的进程通信就可以利用这个标志和其他进程进行交互。 网络中的进程是通过socket来通信的,因为linux观念就是"一切皆文件",都可以用打开->读写->关闭 来操作。socket就可以用这个模式来实现,一些socket函数就是对其进原创 2020-11-16 22:11:21 · 594 阅读 · 0 评论 -
TCP/IP 第一篇概念
这里主要讲TCP协议的概念和简单实现TCP协议1.网络模型1.七层网络模型2.五层网络模型3. 四层网络模型2.TCP头部3.TCP状态流转4.TCP超时重传5.TCP滑动窗口6.TCP拥塞控制TCP协议传输层的协议主要有两个:TCP和UDP协议。TCP相对UDP协议的特点是:面向连接、字节流和可靠传输。使用TCP协议通信的双方必须先建立连接,然后才能开始数据的读写。TCP连接是全双工的,即双方的数据读写可以通过一个连接进行。完成数据交换后,通信双方都必须断开连接以释放系统资源。TCP传输是可靠的。首原创 2020-11-15 23:02:44 · 133 阅读 · 0 评论 -
Linux多线程
创建线程#include <pthread.h>int pthread_create(pthread_t *tidp,const pthread_attr_t *attr,void *(*start_rtn)(void),void *arg)tidp:线程idattr:线程属性(通常为空)start_rtn:线程要执行的函数arg:start_rtn的参数编译的时候需要加...原创 2018-12-08 15:33:05 · 132 阅读 · 0 评论 -
Leetcode 刷题1
例题一:链表逆序 leetcode206已知链表头结点指针head,将链表逆序。(不可申请额外空间)依次遍历链表节点,每遍历一个节点即逆置一个节点ListNode *reverseList(ListNode * head){ ListNode* new_head = NULL; while(head){ ListNode * next = head->next; ...原创 2019-06-30 22:31:57 · 168 阅读 · 0 评论 -
STL的erase()陷阱-迭代器失效总结
https://www.cnblogs.com/blueoverflow/p/4923523.html转载 2019-08-11 12:33:41 · 96 阅读 · 0 评论 -
背包、完全背包、多重背包问题的C++实现
https://blog.csdn.net/m0_37830950/article/details/70240661转载 2019-09-10 17:01:43 · 964 阅读 · 0 评论