- 博客(281)
- 资源 (1)
- 收藏
- 关注
原创 extern C介绍
基本概念extern “C” 是 C++ 中的一个链接规范(linkage specification),用于指定函数或变量使用 C 语言的链接规则。主要作用解决名称修饰(Name Mangling)问题cpp// C++ 编译器会对函数名进行名称修饰// 可能被修饰为 _foo_i// 可能被修饰为 _foo_d// 可能被修饰为 _foo_i_i// 使用 extern “C” 禁止名称修饰// 保持为 bar3. 基本语法单个函数声明cpp。
2025-11-20 16:25:52
654
转载 堆和栈的区别
当主函数要调用一个函数的时候,要对当前断点进行保存,需要使用栈来实现,首先入栈的是主函数下一条语句的地址,然后是调用函数的参数,一般情况下是按照从右向左的顺序入栈,之后是调用函数的局部变量,注意静态变量是存放在全局内存区,是不入栈的;栈,是一种向低地址扩展的数据结构,并且是连续的存储空间,所以栈顶和栈的最大容量是固定的,在windows下,栈的最大容量是2m或者是1m,是在编译的时候就已经确定的,当申请空间大于栈的剩余空间的时候,就会报错说明overflow,所以栈能够申请的空间是比较有限的。
2025-11-20 15:56:17
10
原创 虚析构函数的重要性
/ ❌ 只调用Base的析构函数,Derived的析构函数不会被调用!void acquire() override { /* 数据库特定的获取逻辑 */ }void draw() const override { /* 绘制圆形 */ }void draw() const override { /* 绘制矩形 */ }~Derived() override { // ✅ 正确调用派生类析构函数。void operation() override { /* 实现 */ }// 动态分配的资源。
2025-11-20 10:49:38
778
原创 a++、++a区别
2.在自定义数据类型时(主要指有类的情况),由于++a可以返回对象的引用,而a++一定要是返回对象的值(因为局部对象不能返回引用)。a=a+1: 虽然有点雷同于a+=1,但不同的是此时右值的a和1做相加操作,形成一个副本然后赋值给a,所以有额外操作。1.在内建数据类型时(即自增表示式的结果没有被使用,只是简单的用于递增操作),这时这两个表达式的效率是相同的。鉴于a++和++a的差别,C++Primer建议用++a作为for循环的递增量。a++:a先创建自身的一个副本,然后a自增1,最后返回副本的值。
2025-11-20 10:48:21
177
原创 UNUSED_ARG介绍
/ 必须传递user_data参数。UNUSED_ARG 是一个宏,用于显式标记函数中未使用的参数,主要目的是消除编译器警告并提高代码可读性。这是一个简单的宏,但在大型项目和跨平台开发中非常有用,能够保持代码的整洁和编译的清洁。// 使用 UNUSED_ARG - 无警告。消除编译器警告:关于未使用参数的警告。提高代码可读性:明确表达设计意图。保持接口兼容性:符合函数签名要求。支持未来扩展:保留参数供后续使用。示例3:算法库中的占位参数。2. 函数指针兼容性。示例1:信号处理函数。
2025-10-27 14:57:08
135
原创 关于stub和mock
第一部分:C/C++中的Mock和Stub区别基础概念在C/C++单元测试中:Stub(打桩):提供预设的返回值Mock(模拟):验证函数调用行为。
2025-10-27 10:13:30
146
原创 对象注册机制
这种模式在框架开发、插件系统、对象池、服务定位器等场景中非常常见,是一种强大的对象管理技术。aMap:通常是一个全局或静态的映射容器(如 std::map, std::unordered_map)aMap[n] = this 在构造函数中通常表示一种对象注册机制。自动注册:对象在创建时自动将自己注册到全局管理系统中。集中管理:所有同类对象可以在一个地方统一管理。查找机制:提供通过键值快速查找对象的能力。this:指向当前正在构造的对象的指针。整体意思:将当前对象注册到全局映射表中。场景2:消息处理器注册。
2025-10-21 14:22:09
141
原创 shell中的[]和[[]]比较
在Shell中,[ 和 [[ 都是用于条件测试的,但它们之间有一些重要的区别。[ 是传统Bourne shell的测试命令,而 [[ 是Bash等现代shell引入的增强版测试命令。下面详细说明它们的区别:语法和功能:[ 是一个内置命令,同时也是一个外部命令(通常是/bin/[),它要求参数和操作符之间必须有空格,并且最后一个参数必须是 ]。[[ 是一个Shell关键字,它提供了更强大的功能,比如模式匹配和正则表达式匹配,并且不需要对变量进行引号保护(因为不会进行单词分割和路径扩展)。字符串比较:在 [ 中
2025-10-21 13:57:01
283
原创 30 天自制 C++ 服务器--Day4
另一点是我们的程序会变得越来越长、越来越庞大,虽然现在才不到100行代码,但把所有逻辑放在一个程序里显然是一种错误的做法,我们需要对程序进行模块化,每一个模块专门处理一个任务,这样可以增加程序的可读性,也可以写出更大庞大、功能更加复杂的程序。仅仅六行代码就可以实现和之前一样的功能,这样的使用方式忽略了底层的语言细节,不用在程序中考虑错误处理,更简单、更加专注于程序的自然逻辑,大家毫无疑问也肯定希望以这样简单的方式使用socket。C++是一门面向对象的语言,最低级的模块化的方式就是构建一个类。
2025-09-18 10:42:26
417
原创 C++中的template介绍
模板是C++中最强大和复杂的特性之一,它支持泛型编程(Generic Programming),允许编写与类型无关的代码。模板使得我们可以创建通用的函数和类,这些函数和类可以处理多种数据类型,而无需为每种类型重写代码。
2025-09-02 16:45:05
342
1
原创 C++中的assign函数
assign函数是C++标准库中许多容器类(如vector、list、string等)提供的成员函数,用于替换容器中的内容。它提供了一种灵活的方式来修改容器内容,比直接赋值更灵活。
2025-09-02 13:58:29
632
原创 30 天自制 C++ 服务器--Day3
的核心原理在于改变事件通知模型:它通过在内核使用红黑树高效管理注册的文件描述符,利用回调函数在事件发生时直接将就绪项放入链表,并通过 epoll_wait 仅返回实际就绪的事件列表,辅以 mmap 减少数据拷贝。IO复用的基本思想是事件驱动,服务器同时保持多个客户端IO连接,当这个IO上有可读或可写事件发生时,表示这个IO对应的客户端在请求服务器的某项服务,此时服务器响应该服务。epoll监听事件的描述符会放在一颗红黑树上,我们将要监听的IO口放入epoll红黑树中,就可以监听该IO上的事件。
2025-07-16 15:02:04
1366
原创 effective c++---别让异常逃离析构函数
在C++中,从析构函数抛出未捕获的异常会导致程序崩溃(直接调用std::terminate)。// ❌ 致命错误!std::fstream:析构调用close(),但关闭错误仅设置failbit,不抛出。file.close()) { // 假设close()可能抛出异常。void close() { // 用户主动调用,可处理异常。// 必须确保close()不抛出。// 若析构函数抛出异常,程序直接终止,无法到达这里。提供close()/release()等方法。// 可安全抛出(但通常仍不建议)
2025-07-14 16:50:01
313
原创 30 天自制 C++ 服务器--Day2
然而对于socket,bind,listen,accept,connect等函数,我们都设想程序完美地、没有任何异常地运行,而这显然是不可能的,不管写代码水平多高,就算你是林纳斯,也会在程序里写出bug。,这个函数会打印出errno的实际意义,还会打印出我们传入的字符串,也就是第函数第二个参数,让我们很方便定位到程序出现错误的地方。到现在最简单的错误处理函数已经封装好了,但这仅仅用于本教程的开发,在真实的服务器开发中,错误绝不是一个如此简单的话题。通常来讲,当一个系统调用返回-1,说明有error发生。
2025-07-14 16:34:28
169
原创 Effective C++之定义式和声明式
定义式的作用是为编译器提供声明式(declaration)所缺失的详细信息,使得编译器能够正确生成代码或分配内存。定义式(Definition):提供声明所缺失的细节,使得编译器可以实际使用该名称(分配内存、生成代码等)。std::size_t numDigits(int number) { // 定义式:提供函数体。声明式仅告诉编译器“这是什么”,而定义式告诉编译器“这是什么以及如何实现/分配”。// 定义式:编译器为 x 分配内存。class Widget { // 定义式:列出类的成员。
2025-07-14 10:46:55
309
原创 30 天自制 C++ 服务器--Day1
socket 的原意是“插座”,在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。我们把插头插到插座上就能从电网获得电力供应,同样,为了与远程计算机进行数据传输,需要连接到因特网,而 socket 就是用来连接到因特网的工具。socket是什么?
2025-07-11 15:42:04
686
原创 timewait和msl介绍
修改内核参数(如 net.ipv4.tcp_tw_reuse、net.ipv4.tcp_tw_recycle,但后者在 Linux 4.12 后已移除)。此时连接并未立即关闭,而是会等待一段时间(通常是 2×MSL)后才彻底释放资源(如端口、内存等)。MSL 是报文的最大生存时间,TIME_WAIT 的持续时间(2×MSL)由它决定。避免旧连接的延迟报文干扰新连接:防止网络中延迟的旧数据包被误认为是新连接的数据。是 TIME_WAIT 计算的基础(TIME_WAIT = 2×MSL)。
2025-07-09 14:45:58
401
原创 poll的介绍
poll 是 Linux/Unix 系统中用于 多路复用 I/O 操作 的系统调用,允许程序同时监听多个文件描述符(File Descriptor, FD)的状态变化(如可读、可写、错误等)。水平触发(LT):就绪事件需及时处理,否则会重复通知(对比 epoll 的 ET 模式)。-1 出错(如被信号中断),可通过 errno 获取错误码(如 EINTR)。事件驱动:当任一被监听的 FD 就绪(如数据可读、可写)时,立即返回。效率 高(无需每次重置 FD 集合) 低(需每次重建 fd_set)
2025-07-07 17:05:09
983
原创 #if 0介绍
在C/C++中,#if 0 是一种条件编译指令,其作用是临时或永久禁用一段代码,使其不会被编译器处理(相当于“注释掉”代码)。多行注释 /* */ 不能嵌套,而 #if 0 可以嵌套禁用包含注释的代码。#if 0 是代码的“开关”:比注释更灵活,适合临时禁用大段代码或条件编译。必须配对:#if 0 必须有对应的 #endif,否则编译报错。printf(“这段代码不会编译”);若需恢复代码,只需将 #if 0 改为 #if 1。#if 0 可以保留代码语法高亮,方便后续恢复。#if 0 直接禁用代码。
2025-07-07 10:27:01
459
原创 VRRP(Virtual Router Redundancy Protocol)详解
VRRP(虚拟路由器冗余协议)是一种网络容错协议,用于在多台路由器之间实现网关冗余,确保当主路由器故障时,备份路由器能无缝接管流量,从而保障网络的高可用性。它通过虚拟IP(VIP)和虚拟MAC地址实现透明切换,对终端设备无感知。厂商文档:华为《VRRP配置指南》、思科《HSRP vs VRRP》
2025-07-04 15:14:05
159
原创 粘包问题介绍
粘包问题是 基于流的传输协议(如TCP) 中的一种常见现象,指的是发送方连续发送的多个数据包,在接收方缓冲区中被合并成一个“大包”,导致接收方无法正确解析原始数据包的边界。缓冲区机制:为提高效率,TCP 可能合并多次发送的小数据包(Nagle算法)。接收方:可能一次性读取到 包A+包B(粘包),或分多次读取(半包)。发送方:快速连续发送多个小包(如 包A + 包B)。用特殊字符标记包结束(如 \r\n、0x00)。解决方案:长度字段(推荐)、分隔符、固定长度。在包头添加长度字段,明确告知接收方包体大小。
2025-07-03 17:40:31
660
原创 wireshark介绍和使用
Follow TCP Stream(右键数据包 → Follow → TCP Stream):查看完整会话(如 HTTP 请求/响应)。点击数据包:查看协议层级(如 Ethernet → IP → TCP → HTTP)。Statistics → Conversations:查看通信对端(IP/端口)。示例脚本目录:/usr/share/wireshark/plugins/官网:https://www.wireshark.org/基础流程:选择网卡 → 抓包 → 过滤 → 分析。
2025-07-03 17:29:56
726
原创 DPDK介绍与使用
首先确保您已经按照前面的指南安装并配置好了 DPDK 环境。学习 rte_ring、rte_mbuf 等核心数据结构。3.2 filter.c - 过滤器实现。3.3 main.c - 主程序。3.2 下载并编译 DPDK。3.4 绑定网卡到 DPDK。3. DPDK 安装与配置。根据自定义规则过滤数据包。3.3 配置大页内存。
2025-07-03 17:23:02
498
原创 mailbox 核间通信
Mailbox(邮箱) 是一种常见的核间通信(Inter-Processor Communication, IPC)机制,主要用于多核处理器(如ARM多核SoC、FPGA+CPU异构系统)或主从处理器(如MCU与DSP、CPU与GPU)之间的数据交换。Mailbox 是一种高效、低延迟的核间通信方式,适用于多核/异构系统的实时数据交换。在嵌入式Linux、RTOS及SoC设计中广泛应用,需结合硬件特性和软件框架灵活使用。
2025-07-01 16:48:28
1361
原创 缓冲区(Buffer)介绍与实现
环形缓冲区是高效的数据缓存方案,尤其适合高并发实时系统。核心实现:循环数组 + head/tail 指针 + 状态标记(full)。扩展优化:无锁设计、动态扩容、批量操作。经典应用:生产者-消费者模型、音视频流、网络通信。
2025-06-30 16:57:39
577
原创 static线程安全
public:// 声明classVar++;// 必须在类外定义静态成员t1.join();t2.join();// 应为 2return 0;规则:静态类成员需在类外单独定义(链接器需要实际存储)。修改时同样需要加锁。
2025-06-30 16:43:53
584
原创 生产者-消费者模型 和 操作系统信号定时调度
线程安全队列 使用互斥锁(pthread_mutex_t)和条件变量(pthread_cond_t)保护。使用 pthread_mutex_t 和 pthread_cond_t 实现同步。生产者定时器(SIG_PRODUCER)每 1 秒 触发一次。消费者定时器(SIG_CONSUMER)每 2 秒 触发一次。信号处理函数仅设置标志位,线程检测到标志位后执行任务。消费者线程 由另一个定时器信号触发,从队列读取数据。生产者线程 由定时器信号触发,向队列写入数据。
2025-06-27 10:49:44
229
原创 缺页中断(Page Fault)详解
缺页中断是操作系统中内存管理的关键机制,当进程访问的虚拟内存页面不在物理内存(RAM)中时,由 MMU(内存管理单元) 触发 CPU 异常,操作系统通过中断处理程序将缺失的页面从磁盘(如交换空间或文件系统)加载到内存,使进程继续执行。访问非法地址(如空指针),触发 段错误(Segmentation Fault),终止进程。页面在磁盘(交换空间或文件),需从磁盘加载到内存(I/O 操作,速度慢)。首次访问分配的内存时触发软/硬缺页(实际分配物理页面)。重新执行引发缺页的指令,此时页面已在内存,正常访问。
2025-05-30 10:10:49
833
原创 pmap中的mode列,脏页,写时复制
写时复制(Copy-on-Write,简称 COW) 是一种计算机编程中的优化技术,主要用于内存或存储资源的管理。其核心思想是:只有在真正需要修改数据时,才会执行实际的复制操作,从而避免不必要的资源开销。当某个进程尝试修改数据时,系统才会透明地为该进程创建一份独立的副本,后续修改仅影响副本,其他进程仍访问原始数据。多个进程/线程访问同一份数据时,最初共享同一份物理资源(如内存页、文件块),而不是立即创建副本。USS 可以通过pmap的所有值减去共享的包括-s的内存部分,得到吗?
2025-05-20 17:57:23
272
原创 vim的操作
宏: 是一组命令的录制,可以快速重放,适用于重复性操作。寄存器: 是存储文本、命令和宏的临时存储区,允许用户灵活地管理和使用这些数据。通过理解宏和寄存器的概念,您可以更高效地使用 Vim 进行文本编辑和操作。在 Vim 中,是一系列组合命令,涉及到插入模式和普通模式的操作。这段命令的作用是从当前光标位置向右移动 24 个字符,然后向下移动 4 行,删除该位置到当前行末尾的文本,最后在当前行末尾粘贴之前删除的文本。这可以用于快速编辑文本,特别是在处理块选择和文本替换时。cd ~ls -a。
2025-04-02 14:42:38
1269
原创 gdb使用
watchpoint是gdb中一个非常有用的功能,可以帮助开发者监视变量的变化,便于调试和分析程序的行为。通过设置 watchpoint,您可以更轻松地找到导致变量变化的代码位置。
2025-04-01 16:34:57
795
原创 多线程介绍
堆的共享特性要求在访问时注意线程安全,而栈的独立性使得线程之间的局部变量不会相互干扰。例如,线程 A 使用 malloc 分配内存,线程 B 也可以使用 malloc 分配内存,但需要确保对共享数据的访问是安全的。这意味着在同一个进程中的不同线程可以动态分配和释放堆内存。由于堆是共享的,多个线程可以同时访问和修改堆中的数据,这可能导致数据竞争和不一致性的问题。线程 A 和线程 B 各自的栈中可以有相同名称的局部变量,但它们是独立的。由于每个线程有独立的栈,因此线程之间的局部变量是相互隔离的,不会相互影响。
2025-03-25 14:51:15
472
原创 笔试面试01 c/c++
时间复杂度:表示算法执行所需时间的增长率,通常用大 O 表示法表示(如 O(n)、O(log n))。评估算法的效率通常通过分析其时间复杂度和空间复杂度,比较不同算法在处理相同问题时的性能。:由节点组成的线性数据结构,每个节点包含数据和指向下一个节点的指针。:后进先出(LIFO)的数据结构,支持 push 和 pop 操作。给定一个数组,编写一个函数,找出数组中的最大值和最小值。:先进先出(FIFO)的数据结构,支持入队和出队操作。如何评估算法的效率?:层次结构的数据结构,常见的有二叉树、二叉搜索树等。
2025-03-25 14:30:18
675
原创 /proc/[pid]/maps介绍和pmap介绍、RSS、ldd、nm、strace
proc/[pid]/maps 是 Linux 系统中的一个虚拟文件,提供了关于特定进程(由 pid 指定)内存映射的信息。这个文件包含了进程的虚拟地址空间的详细信息,包括每个内存区域的起始和结束地址、权限、偏移量、设备和 inode 信息,以及映射的文件名(如果有的话)。调试:开发人员可以使用 /proc/[pid]/maps 来查看进程的内存布局,帮助调试内存相关的问题。/proc/[pid]/maps 文件只能被拥有该进程的用户或具有足够权限的用户访问。
2025-03-20 16:45:07
613
原创 Dump 文件介绍
实现 dump 文件的生成通常涉及触发程序崩溃并配置系统以允许生成转储文件。生成的 dump 文件可以用于后续的调试和分析,帮助开发人员识别和修复程序中的错误。在 Windows 中,系统转储可以是小型转储(只包含内核信息)、完整转储(包含所有内存)或内核转储(只包含内核内存)。每种类型的 dump 文件都有其特定的用途和分析方法,开发人员可以根据需要选择合适的类型进行调试和故障排除。用户模式转储可以是完整的(包含所有内存)或小型的(仅包含活动线程的堆栈和一些关键数据)。它们可以用于后续分析和调试。
2025-03-14 18:01:00
680
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅