【QT入门到晋级】内存

发布时间:2026/10/22 1:22:16

【QT入门到晋级】内存 前言本文从“在C/C开发时选用哪种内存处理方式较好”的角度聊聊内存的使用。主要还是站在需要开发后台功能的QT开发者的角度来写的总结笔记。内存分布我们开发的应用程序运行时为了确保确保系统稳定性通常应用程序是在用户态下运行只能访问操作系统为其分配的‌用户空间内存‌。临时变量、局部变量等临时值通常存储在用户态的栈空间或寄存器中全局变量、静态常量、静态数组等生命周期为整个程序运行期的通常存储在用户态的静态存储区数据段或BSS段动态数组如new、malloc、calloc、realloc等申请的内存、 STL容器(vector、list、map) 等通常存储在用户态的堆空间中通过malloc或new申请动态内存时尝试从用户态的堆内存池中分配内存若用户态堆中有足够空闲内存块则直接返回给应用程序若用户态的堆内存不足时C库会通过系统调用如brk或mmap向内核申请扩展堆空间应用程序不需要关注此操作。通过‌内存映射文件‌技术(mmap)申请的内核动态内存内核会为用户态应用进程分配虚拟地址空间这个虚拟机地址空间是在用户态地址空间中分配并建立与物理内存或文件的映射关系。以下是单个应用进程3类分布区对比声明以下表格来源于AI辅助创作‌特性‌‌栈(Stack)‌‌静态存储区(Static Area)‌‌堆(Heap)‌‌典型应用场景‌临时变量、局部变量全局变量、静态常量、静态数组动态数据、大对象‌分配方式‌编译器自动分配/释放调整栈指针编译期固定地址分配运行时动态分配malloc/new‌访问速度‌最快仅次于CPU寄存器次之直接寻址最慢间接寻址‌生命周期函数调用周期程序运行周期手动控制或GC管理‌内存连续性‌连续存储连续存储非连续链表结构‌大小范围‌Linux‌: 2-10MBWindows‌: 1-8MB单变量/数组不超过几百MB理论是所有系统剩余虚拟内存申请越多碎片越严重‌管理开销‌无自动管理无编译期确定高需维护空闲链表/内存池‌线程安全‌线程独占无需同步可能需同步全局共享需同步多线程共享‌碎片问题‌无无易产生碎片‌分配失败后果‌栈溢出程序崩溃编译期错误返回NULL需错误处理开发运用栈的应用栈空间是最小的也是执行最快的适合存放‌小型、生命周期短且大小固定的数据因为有大小限制如果申请大数据容易导致程序崩溃例如int arr[1000000]约4MB可能超出栈默认大小引发栈溢出。以下通过读取文件内容的场景来对比//正确方式不管文件有多大每次读取1KB到栈中 std::ifstream file(large_file.bin, std::ios::binary); char buff[1024]; // 1KB栈缓冲区 while (file.read(buff, sizeof(buff))) { // 处理当前块buff中数据 } //错误方式10MB栈缓冲区导致程序崩溃 std::ifstream file(large_file.bin, std::ios::binary); char buff[1024*1024*10]; // 10MB栈缓冲区 while (file.read(buff, sizeof(buff))) { // 处理当前块buff中数据 }如果硬要申请很多的数据缓存可以把数组char buff[1024*1024*10];搬到外面作为静态数组用或者改成vector(动态内存)方式来用下面给出改成动态内存方式的样例const size_t buffer_size 1024 * 1024 * 20; // 20MB缓冲区 std::vectorchar buff(buffer_size); // 堆分配缓冲区 std::ifstream file(large_file.bin, std::ios::binary | std::ios::ate); while (file.read(buff.data(), sizeof(buff))) { // 处理当前块buff中数据 }总结临时变量、局部变量不能申请太大的数组缓存主要是关注大数组或者是包含大数组的结构体即可。静态存储区的应用静态存储区与栈很接近运行效率稍微比栈低但空间比栈大而且作用域是整个全局如果频繁要用到某个常量/变量/数组那么就适合设置为全局变量、静态常量、静态数组。全局变量、静态常量太常用了这里举个静态数组的场景处理指定目录下存在待入库到mysql的文件// 数据结构体 struct stCollectMsg { int id; char name[64]; double value; char timestamp[20]; }; const int BATCH_SIZE 100; stCollectMsg sqldata[BATCH_SIZE]; // 静态数组 // 文件读取函数 void ReadFile(const char* filename) { std::ifstream file(filename, std::ios::binary); int current_count 0; while (!file.eof()) { //读取数据 file.read((char*)sqldata[current_count], sizeof(stCollectMsg)); if (file.gcount() sizeof(stCollectMsg)) { //数量时把数据插入数据库 if (current_count BATCH_SIZE) { InsertData(conn, sqldata, current_count); current_count 0; } } } // 处理剩余数据 if (current_count 0) { InsertData(conn, sqldata, current_count); } } // 数据入库函数 void InsertData(MYSQL* conn, stCollectMsg* data, int count) { std::string query INSERT INTO collect_data (id, name, value, timestamp) VALUES ; for (int i 0; i count; i) { query ( std::to_string(data[i].id) , data[i].name , std::to_string(data[i].value) , data[i].timestamp ); if (i ! count - 1) query ,; } if (mysql_query(conn, query.c_str())) { std::cerr 入库失败: mysql_error(conn) std::endl; } }组装多条数据一次入库比一条一条入库效率快很多类似的场景很多。堆的应用静态数组能做的申请堆内存的动态数组也能做区别是堆上申请的内存是不连续的导致整体性能没有动态数组和静态数组效率快。但是堆更灵活也更大适合大对象数据以及规模大的数据量处理。比如视频类数据都是以G为单位最好放在动态内存中。虚拟地址空间使用mmap进行内存映射时用户空间会创建虚拟地址区域同时与物理内存建立映射关系应用进程以访问虚拟地址的方式来访问真实的物理内存。以下通过与动态内存对比来加深了解声明以下表格来源于AI辅助创作对比维度mmap内存映射动态内存分配(malloc/free)‌工作原理‌将文件/设备映射到进程虚拟地址空间建立直接访问通道通过系统调用从堆(heap)分配内存块返回可操作指针‌内存来源‌文件数据或匿名映射区(不关联文件)堆内存空间‌系统开销‌建立映射开销较大(需修改页表)适合长期使用的内存区域分配/释放操作轻量适合频繁变动的内存需求‌管理机制‌由操作系统内核管理映射关系自动处理页错误需程序员手动管理分配/释放依赖内存管理器实现(如ptmalloc、jemalloc)‌性能特点‌• 大文件访问减少拷贝开销• 缺页中断影响随机访问性能• 小内存分配效率高• 频繁分配/释放可能产生碎片‌内存限制‌受虚拟地址空间限制(32位系统约3GB用户空间)受物理内存swap空间限制‌线程安全‌映射区域自动共享需额外同步机制分配器本身线程安全但使用需加锁‌典型问题‌• 内存映射对齐要求(通常4KB)• msync同步策略选择• 内存泄漏风险• use-after-free漏洞• 碎片化导致分配失败‌优势场景‌• 大文件随机访问(数据库索引)• 进程间共享内存• 零拷贝数据传输• 灵活分配任意大小内存• 实时内存需求处理• 短生命周期对象‌适用场景‌• 数据库引擎• 大型媒体文件处理• 进程间通信• 动态数据结构• 临时缓冲区• 运行时确定大小的对象总结mmap在内存映射时开销比较大处理小数量的内存/数据性能较低其优势场景是适合大文件读写以及多个进程共享一段内存。比如一段高清监控视频可以结合共享内存内存映射提供查看进程、AI分析进程、质量分析进程等多个进程同时访问这种设计方式比每个进程自己加载一段高清监控视频到自己的动态区域后再进行分析的设计方式节省内存以及节省IO操作的开销。以下给出内存映射与常规IO操作对比表声明以下表格来源于AI辅助创作对比维度mmap操作read/write操作工作原理将文件直接映射到进程地址空间通过内核缓冲区进行数据中转优势场景• 随机访问大文件数据库/B树• 频繁访问相同文件区域• 进程间共享内存• 顺序读写日志文件• 流式处理视频编码• 精确控制I/O时序性能表现• 大文件随机访问快3-5倍• 零拷贝网络传输优势• 小文件操作快20-30%• 流式数据吞吐量稳定内存影响可能引发大量缺页中断需预加载策略内核缓冲区可控可调节buffer大小数据安全依赖msync同步默认异步写入同步写入保证数据持久化适用文件大小1MB文件效益明显1MB文件效率更优多进程协作天然支持MAP_SHARED需额外IPC机制复杂度需处理页对齐问题4KB倍数编程模型简单直接典型应用• 数据库引擎• 机器学习模型加载• 地理空间数据处理• 日志收集系统• 压缩包处理• 网络协议栈实现系统限制受限于虚拟内存空间32位系统最大2-3GB仅受物理存储限制
延伸阅读

更多相关文章

2026/10/22 1:22:16

如何快速上手安卓投屏与控制:Scrcpy 完整指南

如何快速上手安卓投屏与控制:Scrcpy 完整指南 【免费下载链接】scrcpy Display and control your Android device 项目地址: https://gitcode.com/GitHub_Trending/sc/scrcpy 把手机画面投到电脑屏幕,还能直接用键盘鼠标操作手机——Scrcpy&#…

2026/10/22 2:42:27

大模型偏好调优:从奖励模型到RLHF与DPO的实战指南

大模型能不能“写一手好文章”“回一句得体的建议”,很多时候靠的不是它背了多少数据,而是它在“什么算好、什么算差”这件事上有没有被教明白。早期大家发现,单纯靠预训练加指令微调,模型可以做到“有问必答”,但回答…

2026/10/22 2:42:27

AI重塑企业业务流程:八大场景、实施方法与避坑指南

1. 先聊清楚:AI重塑业务流程到底在重塑什么过去一年我走访了不少企业,从几百人的制造工厂到几千人的连锁零售公司,大家都在聊AI,但绝大多数都卡在同一道坎上:不知道从哪个环节切入,也不知道AI换掉老流程之后…

2026/10/22 2:42:27

SLES等保测评命令全解析:从身份鉴别到审计日志的检查与整改

做等保测评的人最清楚,进到一台SUSE Linux Enterprise Server面前,满屏命令里到底哪些是测评项该看的,哪些只是系统运行的正常输出,这中间隔着一整套安全控制点的理解。SLES在企业里多是核心业务的承载系统,等保2.0要求…

2026/10/22 2:42:27

MIMO技术实战:从信道估计到自适应层数的工程落地指南

简介:这份PDF文档系统梳理了MIMO(多输入多输出)无线通信技术的发展脉络,面向通信工程、电子信息类专业学生及移动通信技术研究者,帮助读者建立从原理到应用的完整认知框架。文档从MIMO技术的基本概念入手,阐…

2026/10/22 2:37:23

Honeywell EPKS SafeView配置实战:只读监控界面的正确打开方式

简介:本资源是一份面向Honeywell EPKS系统操作员与DCS工程技术人员的实战型配置指南,聚焦SafeView这一关键人机界面管理功能,解决工业现场Windows通用桌面环境下画面混乱、关键信息易被遮挡、多应用协同低效等典型问题。文档基于Honeywell标准…

2026/10/21 4:53:08

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/22 0:01:49

电商智能运营体系从0到1:架构设计、落地步骤与避坑指南

前两年我们团队接了一个电商平台的运营中台项目,目标很直白:把过去靠运营拍脑袋做的选品、定价、发券、推活动这些事,逐步用数据算法和自动化流程代替。项目名字内部就叫“电商智能运营体系”。最近有不少朋友问我当时是怎么设计的、踩过哪些…

2026/10/22 0:01:49

若依框架AI代码生成不稳定?用Agent Skill三层结构+五步法搞定

最近一段时间,我一直想把后台管理系统里那些机械重复的增删改查代码交给AI去写。框架用的是若依,按理说这类业务代码模式非常固定,应该是AI最擅长的事情。可真试下来却不是那么回事——你让AI生成一个用户管理模块,它给出的Contro…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑