c++
文章平均质量分 91
落樱弥城
无无
展开
-
简要描述C++ Memory Order
memory_order_relaxed: 最宽松的内存顺序, 只保证操作的原子性和修改顺序 (modification order).原创 2024-07-06 23:11:46 · 796 阅读 · 0 评论 -
C++异常处理实现(libstdc++)
为了更好的理解C++中异常处理的实现,本文简单描述了Itanium ABI中异常处理的流程和llvm/libsdc++简要实现。原创 2024-05-05 17:10:01 · 1281 阅读 · 0 评论 -
正确对你的C++代码进行性能测试——DoNotOptimize实现原理
是google-benchmark提供的一个函数,强制编译器不要对制定的变量进行任何优化。需要注意的是DoNotOptimize强制编译器不要对制定的不指定的编译器月变量优化而不是不对表达式进行优化,也就是说你的表达式可以被优化的化依然会被优化只是结果一定写内存。return a;int a = 1;return 0;不加DoNotOptimize的化testFunc、a和t都会被删除,而编译后的结果如下。可以看到两个变量都是读取的栈内存。1147: 00。原创 2024-05-02 12:53:33 · 481 阅读 · 0 评论 -
C++中volatile的具体含义和可能的坑
提醒编译器不要对该变量相关的代码进行优化,避免出现意外的负面作用;对类似的表达式不进行编译层面的指令重排。编译指令重排也是一种编译器优化手段,这条严格来说也是第一条的变种。int g = 0;a < n;a++) {i++;//func对应的汇编a < n;a++) {j++;//func1 对应的汇编a < n;a++) {g++;//func2对应的汇编上面的代码中可以看到对于普通变量的++直接被编译器在编译期间就分析出来结果,直接赋值了,for循环直接被干掉了。原创 2024-01-22 00:52:43 · 2416 阅读 · 0 评论 -
C++ libcxxabi中dynamic_cast 实现
C++中,用于有虚函数的继承链中父类型到子类型的安全转换。class A{public:class B{如何识别当前类的类型,这依赖于RTTI。C++中包含虚函数的对象都有一个虚函数表,一般情况下都在首地址(多继承和虚继承会有多个)有一个指向该虚函数表的虚函数表指针。基类偏移;typeinfo;如果有虚函数的话会有虚析构函数指针,一般情况下有两个;虚函数指针,如果是虚继承对应的虚函数指针可能是一个thunk function。原创 2023-11-26 22:35:56 · 429 阅读 · 0 评论 -
【crash】 cxa_pure_virtual 崩溃分析与原理
怀疑到这一点,我这边开始找资料(类似的问题印象中标准中是不管的,那大概率在ABI中定义的,那我们去看ABI的定义)。怀疑到这一点,我这边开始找资料(类似的问题印象中标准中是不管的,那大概率在ABI中定义的,那我们去看ABI的定义)。当类被析构时,基类的析构稍微比较耗时时,第二个线程尝试访问当前类的一个被重写的纯虚函数,由于此时的虚函数表中的纯虚函数已经被修改为。当类被析构时,基类的析构稍微比较耗时时,第二个线程尝试访问当前类的一个被重写的纯虚函数,由于此时的虚函数表中的纯虚函数已经被修改为。原创 2023-11-23 00:37:40 · 869 阅读 · 0 评论 -
Folly库实现阅读——FBString
FBString是facebook内部使用的基础库的string组件,为了达到更好的性能采用了多种存储策略,优化不同场景的性能。FBString完全兼容,同时支持jemalloc更快的分配内存,减少磁盘碎片,加快并发情况下的速度和性能。实现细节三种存储策略;与100%兼容。COW 存储时对于引用计数线程安全。对 Jemalloc 友好。如果检测到使用jemalloc,那么将使用jemalloc的一些非标准扩展接口来提高性能。原创 2023-09-24 22:41:10 · 369 阅读 · 0 评论 -
C++对象模型实验(clang虚函数表结构)
本科期间有对比过msvc,gcc,clang的内存布局,距今已经6-7年了,当时还是使用的c++11。时间过得比较久了,这部分内容特别是内存对齐似乎C++17发生了一些变化,因此再实践下C++类模型。本文描述了C++不同类型的实际内存模型实现,主要关注虚函数表的具体内存布局。虽然clang,msvc都提供了对应的命令让我们直接查看类对象的内存布局,但是我们自己解析一下理解更深一点儿。原创 2023-08-20 22:33:20 · 430 阅读 · 1 评论 -
【crash】浮点除0堆损坏
然后就去看代码排查调用链中可能导致堆损坏的地方(因为开发机无法复现,因此只能通过分析+日志来排查),在排查代码过程中发现了几处可能越界的操作以及除0。IEEE754规定了浮点除0运算的结果为+INF或者-INF,但是C++标准明确规定了该行为未定义的,使用可能会导致UB。实际测试过程中发现只有低版本的机器浮点除0是不支持的,而新机器无论是windows还是Mac浮点除0编译器只会报warning但是结果是INF不会出错。,比较反常,因此排查了该值的计算来源发现是有double除0。比较小只有20个元素)。原创 2023-07-14 23:32:34 · 233 阅读 · 0 评论 -
动态库的入口——VCRT(DLL)和CRT(SO)
为了更加深入的理解动态库的加载初始化过程,本文根据VCRT和Linux-CRT的代码实现详细描述了windows和linux平台下对应动态库加载时会进行哪些工作。本文重点关注全局变量的初始化时机,以及是否有其他额外的操作。原创 2023-06-23 00:25:11 · 959 阅读 · 0 评论 -
C++ 反汇编简要
C/C++都需要经过编译器变成对应的机器码,通常编译器对程序员是个黑盒子。有些时候我们可能会纠结编译器会不会进行RVO,EBO等优化,以及一些在我们看起来应该正常的代码因为一些UB的行为被C++编译器优化成了不可预期的代码。这时候如果我们了解具体代码是如何编译成对应的二进制机器码对我们查具体的问题非常有益。另一种场景,在开发软件时,线上环境能够复现的问题,我们本地可能是无法复现的。这就需要我们根据线上的堆栈分析具体的原因。原创 2023-06-19 22:17:28 · 2683 阅读 · 0 评论 -
C++源码剖析——unordered_map和unordered_set
之前看过侯老师的《STL源码剖析》但是那已经是多年以前的,现在工作中有时候查问题和崩溃都需要了解实际工作中使用到的STL的实现。因此计划把STL的源码再过一遍。原创 2023-04-08 21:19:17 · 669 阅读 · 1 评论 -
C++源码剖析——set,multiset,map和multimap
之前看过侯老师的《STL源码剖析》但是那已经是多年以前的,现在工作中有时候查问题和崩溃都需要了解实际工作中使用到的STL的实现。因此计划把STL的源码再过一遍。原创 2023-04-08 18:06:21 · 551 阅读 · 0 评论 -
C++源码剖析——序列容器适配器(stack,queue,priority_queue)
之前看过侯老师的《STL源码剖析》但是那已经是多年以前的,现在工作中有时候查问题和崩溃都需要了解实际工作中使用到的STL的实现。因此计划把STL的源码再过一遍。原创 2023-04-02 22:34:23 · 192 阅读 · 0 评论 -
C++源码剖析——list
之前看过侯老师的《STL源码剖析》但是那已经是多年以前的,现在工作中有时候查问题和崩溃都需要了解实际工作中使用到的STL的实现。因此计划把STL的源码再过一遍。原创 2023-04-02 19:56:27 · 354 阅读 · 0 评论 -
C++源码剖析——forward_list
之前看过侯老师的《STL源码剖析》但是那已经是多年以前的,现在工作中有时候查问题和崩溃都需要了解实际工作中使用到的STL的实现。因此计划把STL的源码再过一遍。原创 2023-04-02 16:19:02 · 394 阅读 · 0 评论 -
C++源码剖析——deque
之前看过侯老师的《STL源码剖析》但是那已经是多年以前的,现在工作中有时候查问题和崩溃都需要了解实际工作中使用到的STL的实现。因此计划把STL的源码再过一遍。原创 2023-04-02 14:53:31 · 836 阅读 · 0 评论 -
C++源码剖析——vector和array
之前看过侯老师的《STL源码剖析》但是那已经是多年以前的,现在工作中有时候查问题和崩溃都需要了解实际工作中使用到的STL的实现。因此计划把STL的源码再过一遍。原创 2023-03-26 12:48:41 · 467 阅读 · 0 评论 -
C++源码剖析——string和string_view
之前看过侯老师的《STL源码剖析》但是那已经是多年以前的,现在工作中有时候查问题和崩溃都需要了解实际工作中使用到的STL的实现。因此计划把STL的源码再过一遍。原创 2023-03-21 00:10:36 · 982 阅读 · 0 评论 -
C++源码剖析——allocator和allocator_traits
allocator是STL中对一个堆内存分配器,是对内存申请工作的一个封装,将内存的申请和成员的构造抽象开来方便控制。基本上,C++标准库中的容器的默认分配器都是allocator。在C++中分配器是通过模板参数的方式指定给对应的容器,默认就是allocator,用户自己也可以实现自己的内存管理类,对堆的内存进行有效的管理也可以将对应的分配器指定给容器使用(前提是接口保持一致)。原创 2023-03-19 16:27:16 · 1127 阅读 · 0 评论 -
C++多线程以及线程池
1 线程1.1 简介 线程(英语:thread)是操作系统能够进行运算调度的最小单位。大部分情况下,它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。 同一进程中的多条线程将共享该进程中的全部系统资源原创 2020-06-10 16:11:46 · 5288 阅读 · 3 评论 -
《Effective STL》阅读笔记
一 容器1 慎重选择容器 STL提供了多种容器,不同容器的应用场景不同,需要充分理解容器的使用场景,并针对性的选择合适的容器。C++中的容器类型包括:标准STL序列容器:vector、string、deque、list;标准STL关联容器:set、multiset、map、multimap;非标准序列容器:slist、rope;非标准关联容器:unordered_set、unordered_multiset、unordered_map、unordered_multimap;标准的非STL容原创 2021-11-19 23:01:24 · 1335 阅读 · 0 评论 -
《More Effective C++》阅读笔记
一 基础议题1 仔细区分pointer和reference 指针和引用的区别:引用是一个标记符别名,而指针是一个变量;引用必须赋予初值且不能修改,指针可以存在空指针可修改;引用没有地址,指针在内存中存在。 指针和引用除了上面的区别外,基本上的行为是一致的,因此在具体使用场景上该使用哪一个主要是看是否会修改指针或者引用指向或者表示的对象,如果会修改则使用指针,不会修改则使用引用。2 最好使用C++类型转换 C中的隐式类型转换或者显式类型转换都应该被弃用,使用用途更加明确的C++类型转原创 2021-10-07 00:32:20 · 266 阅读 · 0 评论 -
《Effective C++:55个提升性能的办法》阅读笔记
一 然自己习惯C++1 视C++为一个语言联邦 C++语言本身的出身和目标和其名称表达的意思相近,作为C语言的超集。C++的最初的目标是在保证对C的完全兼容的前提下扩充面向对象的能力,提升研发效率。典型的就是早期的C with Class版本,但是当C++继续发展出现重载、虚函数、模板之后这一目标已经无法完全保证了。因此无法简单的将C++看作C的超集,只能将其看作部分兼容C的面向对象语言。 为了更加清晰的认识C++可以将C++看作一个由多个次语言组成的语言的集合而不是某个单一语言,而每个次语言的规原创 2021-10-05 23:52:04 · 452 阅读 · 0 评论 -
程序员自我修养阅读笔记——静态链接
测试环境:➜ tmp uname --versionuname (GNU coreutils) 8.25Copyright (C) 2016 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.This is free software: you are free to change and redistribute .原创 2021-09-21 22:59:09 · 386 阅读 · 0 评论 -
程序员自我修养阅读笔记——目标文件里有什么
1 目标文件格式 PC平台的目标文件格式大都是COFF的变种,比如Windows的PE(Portable Executable)格式和Linux的ELF(Executable Linkable Format)格式。并且我们一般讲的目标文件格式多指可执行文件,但是实际上编译过程中的静态库文件、动态库文件和.o或者.obj文件都属于目标文件。常见的目标文件分类:目标文件类型说明举例可执行文件可以直接执行的程序windows的exe文件、linux的可执行文件、macOs的app文原创 2021-09-21 15:24:59 · 1693 阅读 · 2 评论 -
深入探索C++对象模型之站在对象模型的顶端
1 模板具象化:这里的具象化是指编译器需要针对指定的类型参数实例化一个版本的类对象或者函数版本。1.1 模板具象化时机 对于一个模板类的指针或者引用,何时实例化一个具象化版本的模板类,根本依据是当前声明的对象是否需要一个类的完整信息,如果不需要则不进行实例化,如果需要则进行。 模板类的成员函数应不应该被具象化,也就是说当需要具象化一个版本的类时,需不需要把其对应的具象化版本的成员函数也具象化出来。C++标准要求只有当成员函数被使用时才进行相关的具象化。但是并不是所有的编译器都会遵从这个要求,原创 2020-12-22 16:52:12 · 183 阅读 · 0 评论 -
深入探索C++之执行期语义学
主要谈论程序执行期全部,局部,堆,临时对象的构造和销毁时机。1 对象构造和析构1.1 全局变量 一般来说,局部对象的构造和销毁时机都和一般的认为相同,在定义处进行构造调用constructor,在离开当前作用域时销毁调用destructor。但是有时候会带来性能上额外的负担,一般建议类的定义尽可能放置于需要使用该类的作用域附近,可以节省一些不必要的对象构造和销毁操作的性能消耗。 对于全局变量,编译器一定能够保证在程序中第一次使用该全局变量之前初始化或者构造该变量,并在程序结束前销毁。其初始化原创 2020-12-22 14:17:56 · 172 阅读 · 0 评论 -
深入探索C++对象模型之构造析构拷贝语义学
对于抽象类中的纯虚函数并不是严格意义上无法调用,在继承体系中可以调用,但是这种调用并不体现多态属性,只能被静态链接。如果将析构函数定义为纯虚函数将面临很多无必要的麻烦,因此一般不建议将析构函数定义为纯虚函数。另外,对于虚函数是否应该声明为const,一般不建议,因为类的设计者不能假设将来需要继承自当前类的行为。1 无继承类对象构造 在C++中声明只包含简单数据类型的类似C结构的类,将会被打上Plain OI' Data的标签,该数据在进行构建,拷贝,赋值,析构等操作时并不会按照观念上那样调用默认构原创 2020-12-20 20:49:32 · 200 阅读 · 0 评论 -
深入探索C++对象模型之Function语义学
C++中的函数包含普通函数,非静态成员函数,静态成员函数,虚函数,后面三种都和类相关。这里主要讨论成员函数的调用方式和普通的函数的区别。1 不同函数的调用方式1.1 非静态成员函数 C++设计的准则之一就是:非静态成员函数至少必须和普通函数拥有相同的效率。一般情况下编译器都会对类的非静态成员函数进行转换:改写函数原型,将类的this指针作为函数的参数插入函数中;对函数中每一个类的非静态成员变量的存取操作转换为经由this指针访问;将类的非静态成员函数重写为一个外部函数,并未函数名称进行m原创 2020-12-19 22:08:00 · 196 阅读 · 1 评论 -
深入探索C++对象模型之Data语义学
C++中声明一个对象的size是多少,一般主要由几个因素影响:语言本身导致的额外负担。比如c++中的虚函数指针;编译器对特殊情况所提供哦你的处理方式。比如空类size=1;内存对齐。 C++中对象中的变量类型有static,nonstatic,但是static并不存储在对象内存中,因此实际上并不占用对象的内存空间,因此数据空间主要是nonstatic变量。由于C++中多态的存在,一般编译器都会在对象中维护一个虚函数指针用来指向当前对象的虚函数表,因此该虚函数指针是实际占用内存空间的。另外,原创 2020-12-17 21:27:13 · 304 阅读 · 0 评论 -
深入探索C++对象模型之构造函数语义学
C++中编译器背着程序员做了很多事情,导致程序员无法准确的了解到自己所实现的代码本身所具有的性能缺陷。这一章主要谈论C++中构造函数相关的构建行为。1 默认构造函数的构建行为 一般来说,我们认为在构建一个类时,如果程序员并未给类提供任何相关的构造函数,编译器总是会自动生成默认构造函数,但是实际上的行为却并不完全一致,并且编译器一般不会负责初始化类中的成员对象。但是,在一些情况下,编译器的确会生成相关的默认构造函数来完成一些元素的初始化任务。而具体何时生成一般主要看编译器本身是否需要。言外之意,就是原创 2020-12-14 13:44:26 · 224 阅读 · 1 评论 -
深入探索C++对象模型之C++对象(vs,gcc,clang测试)
1 C++对象模型 C中表示结构化数据一般是使用struct,其中操作数据和具体的数据定义时分开的。C++中的对象是将数据和操作方式包装在一起的ADT(抽象数据类型)。在C++中数据成员分为static,nonstatic,而成员函数分为三种:static,nonstatic,virtual。 现在假定有类base,base的声明如下:class base{public: base(int val = 0){} virtual ~base(){} static原创 2020-12-07 21:45:52 · 796 阅读 · 0 评论 -
调用约定
调用约定是一种定义函数从调用处接受参数以及返回结果的方法的约定。 不同调用约定的区别在于:参数和返回值放置的位置(在寄存器中;在调用栈中;两者混合);参数传递的顺序(或者单个参数不同部分的顺序);调用前设置和调用后清理的工作,在调用者和被调用者之间如何分配;被调用者可以直接使用哪一个寄存器有时也包括在内。(否则的话被当成ABI的细节);哪一个寄存器被当作volatile的或者非volatile的,并且如果是volatile的,不需要被调用者恢复。 调用约定与名称修饰(名称修饰决定了原创 2020-08-31 22:18:04 · 1163 阅读 · 0 评论 -
图像的常规边缘检测(梯度算子、Roberts算子和Sobel算子)(纯C++)
1 简述 相关的梯度算子、Roberts算子和Sobel算子等算子的具体原理网上有很多博客进行描述,原理就不再啰嗦了,主要工作就是基于libpng库使用纯C++语言不依赖其他额外的库对三个算子进行了实现。 完整的代码仓库见:边缘检测,具体使用方式见其中的readme.md。2 实现 代码中的thread_pool是自己实现的线程池,用来加速算法。2.1 梯度算子void core::grad_detection::detect_row(core::png_image &src, c原创 2020-08-29 11:27:35 · 1334 阅读 · 0 评论 -
缓存LRU算法C++实现
1. LRU简介 LRU (Least recently used) 最近最少使用算法是缓存置换策略中使用比较多的算法之一。其利用程序的局部性原则:最近访问的缓存将来还会访问的可能性很大。LRU实现比较简单,而且对于实际问题也很实用,良好的运行时性能,命中率较高。 LRU算法的基本算法步骤为:查找希望得到的元素;元素在缓存中则将元素移动到缓存维护的链表的前端;元素不在缓存中则新建节点将该节点添加到链表的前段,如果缓存满则移除链表的最后一个节点。2. LRU实现 LRU算法的实现一般原创 2020-08-14 22:42:10 · 435 阅读 · 0 评论 -
生产者消费者模型
1 问题简介 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多进程同步问题的经典案例。该问题描述了共享固定大小缓冲区的两个进程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。 要解决该原创 2020-07-29 11:55:12 · 174 阅读 · 0 评论 -
创建特殊的C++类
1 创建只能在堆上创建的类 创建只能在堆上创建的类基本思路是让其在栈上创建失败。在栈上创建类程序需要调用构造器和析构器对类对象进行初始化和销毁。 让程序调用析构函数和构造函数失败的实现方式就是将析构函数声明为private或者protected。1.1 析构函数和构造函数全部私有? 最直接的一种写法便是将析构函数和构造函数私有化,另外创建对象创建的接口,只通过在堆上创建相关的对象指针。class test{private: test(){} ~test(){}原创 2020-07-29 11:52:59 · 197 阅读 · 1 评论 -
C++面试知识点
文中涉及语法等都是C++11相关语法。 参考了https://github.com/huihut/interview,文中3.1,3.2,4.1完全来源于该文。 后续有时间继续更新。文章目录@[toc]1 基础相关1.1 C++内存模型1.2 ++,--前缀和后缀的区别1.3 static关键字1.3.1 静态局部变量1.3.2 静态全局变量1.3.3 类的静态成员变量1.3.4 类...原创 2020-03-22 18:22:27 · 341 阅读 · 0 评论 -
《More Effective C++》阅读笔记
在读完《C专家编程》之后收获良多就选择了继续读一些相关的书籍,本打算先看《算法导论》的,但是《算法导论》但是算法导论的篇幅实在太多,无意中在图书馆中发现了这本书就开始阅读,写下这边文档供以后回顾。文中代码调试编译执行平台为window7,vs2013文章目录条款一:仔细区分pointers和references总结条款二:最好使用C++转型操作符1. static_cast<&g...原创 2019-03-18 10:57:04 · 393 阅读 · 0 评论