动态内存操作(2)
接上一篇文章http://t.csdn.cn/1ONDq,这次我们继续讲解关于动态内存的相关知识。
一、常见的动态内存错误
1.对NULL指针进行解引用操作
#include<stdio.h> #include<stdlib.h> #include<limits.h> int main() {int* p = (int*)malloc(INT_MAX/4);*p = 20;//如果没有足够的空间导致p为NULL,就会有问题//所以必须对malloc的返回值进行判断free(p);p = NULL;return 0; }
2.对动态开辟空间的越界访问
int main() {int* p = (int*)malloc(40);if (p == NULL){perror("malloc");return 1;}int i = 0;for (i = 0; i < 11; i++){p[i] = 0;//原本只申请了十个整型的空间,但却访问十一个整型//所以造成越界访问}free(p);p = NULL;return 0; }
3.对非动态开辟的内存使用free释放
int main() {int a = 0;int* p = &a;free(p);//p不是动态开辟的空间,不能释放p = NULL;return 0; }
4.使用free释放动态开辟内存的一部分
int main() {int* p = (int*)malloc(40);if (p == NULL){perror("malloc");return 1;}int i = 0;for (i = 0; i < 5; i++){p[i] = 0;p++;}//p++导致p不再指向这块空间的起始地址//所以如果释放p,等于释放这块空间的一部分(后五个整型空间)//这样就会出问题free(p);p = NULL;return 0; }
5.对同一快动态内存多次释放
int main() {int* p = (int*)malloc(40);if (p == NULL){perror("malloc");return 1;}free(p);//。。。。。free(p);//有时候头脑不清醒就可能释放多次,这样就会出问题return 0; }
6.动态开辟内存后忘记释放内存(最常见)
即我们动态申请内存后,最后忘记用free释放了,这样就会造成内存泄漏。
二、几个关于动态内存的经典例题
例题1、代码运行结果是什么?
源代码:
void GetMemory(char* p) {p = (char*)malloc(100); } void Test(void) {char* str = NULL;GetMemory(str);strcpy(str, "hello world");printf(str); }int main() {Test();return 0; }问:这段代码运行结果会是什么呢?
例题1解答:
一是没有释放动态内存;
二是会产生这样的错误:
原因是:因为在Test函数中,把str指针置空,然后作为参数传给GesMemory函数,该函数形参用指针p接收,这样指针p也为NULL,然后给指针p动态开辟空间,函数结束,到strcpy函数,但我们注意,我们是给指针p开辟空间,但指针str是没有变的,很多伙伴想不清楚,这不是传址调用吗,p指针变了,str指针也应该跟着变呀?
实则不然,我们应该注意参数是指针也不一定是传址调用,这里是指针之间赋值,应该同时上升一段层次,这里要二级指针才算传址调用,所以指针str是不会变的,还是NULL,既然是NULL,所以就没有足够的空间能放下strcpy的第二个参数,所以报错。
例题2、代码运行结果是什么?
char* GetMemory(void) {char p[] = "hello world";return p; } void Test(void) {char* str = NULL;str = GetMemory();printf(str); }int main() {Test();return 0; }问:这段代码运行结果是什么?
例题2解答:
会产生这样的结果:
“很多小伙伴可能觉得,在GetMemory函数里面返回字符串的起始地址p,所以在Test函数里面用指针str来接收并打印,所以运行结果应该为打印字符串。”
但实则不然,我们一定要注意每个变量的生命周期,数组p的生命周期就只在函数GetMemory里面,所以当该函数return后,里面的变量所占的空间都会被自动销毁(释放),既然p的空间已经被释放了,还赋值给指针str,所以str就是个野指针,再打印str,就造成非法访问内存了。
这类问题属于:返回栈空间地址的问题。
三、C/C++程序的内存开辟
如下图:
C/C++ 程序内存分配的几个区域:1. 栈区( stack ):在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。 栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返回地址等。2. 堆区( heap ):一般由程序员分配释放, 若程序员不释放,程序结束时可能由 OS 回收。分配方式类似于链表。3. 数据段(静态区)( static )存放全局变量、静态数据。程序结束后由系统释放。4. 代码段:存放函数体(类成员函数和全局函数)的二进制代码。
实际上普通的局部变量是在 栈区 分配空间的,栈区的特点是在上面创建的变量出了作用域就销毁。但是被static 修饰的变量存放在 数据段(静态区) ,数据段的特点是在上面创建的变量,直到程序 结束才销毁 ,所以生命周期变长。
四、柔性数组
(一)、柔性数组的概念:
//定义一:
struct S
{int a;int arr[0];
};
//定义二:
struct B
{int a;char b;int arr[];
}; (二)、柔性数组的特点:
1、 结构中的柔性数组成员前面必须至少一个其他成员。2、 sizeof 返回的这种结构大小不包括柔性数组的内存,即sizeof只计算柔性数组前面的成员的大小。3、 包含柔性数组成员的结构用 malloc () 函数进行内存的动态分配,并且分配的内存应该大于结构的大 小,以适应柔性数组的预期大小。
(三)、柔性数组的使用:
如下例:struct S {int a;int arr[]; };int main() {//动态开辟了4+40个字节,因为柔性数组是不会被sizeof计算的//前面四个字节是给成员a的,后面四十个字节给柔性数组//因为柔性数组的大小是未知的,我们只需给出预期大小struct S* str = (struct S*)malloc(sizeof(struct S) + 40);//检查if (str == NULL){perror("malloc");return 1;}//使用str->a = 10;int i = 0;for (i = 0; i < 10; i++){str->arr[i] = i + 1;//printf("%d ", str->arr[i]);}//用realloc扩容,因为柔性数组大小未知,是可以改变的//将之前柔性数组的10个字节的大小扩容到15个struct S* p = (struct S*)realloc(str, sizeof(struct S) + 60);//检查if (p == NULL){perror("realloc");return 1;}//使用str = p;for (i = 10; i < 15; i++){str->arr[i] = i + 1;}//打印for (i = 0; i < 15; i++){printf("%d ", str->arr[i]);}//释放free(str);str = NULL;return 0; }
用malloc函数进行开辟空间,用realloc函数进行扩容,这样数组的大小就是可变的、柔性
的,这就是柔性数组的特点。
(四)、柔性数组的优势:
1.方便内存释放:如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给用户。用户调用free 可以释放结构体,但是用户并不知道这个结构体内的成员也需要 free, 所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free 就可以把所有的内存也给释放掉。2.这样有利于访问速度:连续的内存有益于提高访问速度,也有益于减少内存碎片。(其实,我个人觉得也没多高了,反正你跑不了要用做偏移量的加法来寻址)。
相关文章:
动态内存操作(2)
接上一篇文章http://t.csdn.cn/1ONDq,这次我们继续讲解关于动态内存的相关知识。 一、常见的动态内存错误 1.对NULL指针进行解引用操作 #include<stdio.h> #include<stdlib.h> #include<limits.h> int main() {int* p (int*)malloc(INT_MAX/4);…...
Windows-Delphi 窗口置顶
露从今夜白,月是故乡明。 1.Delphi将窗口置顶 if topHwnd <> 0 thenbeginSetWindowPos(topHwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);tmr1.Enabled : True;end; 其中topHwnd是目标窗口的句柄。 2.窗口取消置顶 if topHwnd <> 0 th…...
CVE-2020-11978 Apache Airflow 命令注入漏洞分析与利用
简介 漏洞软件:Apache Airflow影响版本:< 1.10.10 环境 Vulhub 漏洞测试靶场 复现步骤 进入 /root/vulhub/airflow/CVE-2020-11978/ 目录运行以下命令启动环境 # 初始化数据库 docker compose run airflow-init # 开启服务 docker compose up -…...
面试经典算法1:DFS
一、前言 1、题目描述和代码仅供参考,如果有问题欢迎指出 2、解题代码采用acm模式(自己处理输入输出),不采用核心代码模式(只编程核心函数) 3、解题代码采用C语言(ai一键翻译任意语言ÿ…...
Windows系统利用cpolar内网穿透搭建Zblog博客网站并实现公网访问内网!
文章目录 1. 前言2. Z-blog网站搭建2.1 XAMPP环境设置2.2 Z-blog安装2.3 Z-blog网页测试2.4 Cpolar安装和注册 3. 本地网页发布3.1. Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1. 前言 想要成为一个合格的技术宅或程序员,自己搭建网站制作网页是绕…...
SmartCode ViewerX VNC 3.11 Crack
SmartCode ViewerX VNC 查看器 ActiveX 轻松地将 VNC 查看器功能添加到您的应用程序中 SmartCode ViewerX VNC Viewer ActiveX 使开发人员可以使用一组直观的 ActiveX 属性和方法完全访问 VNC 查看器功能。借助ViewerX控件,开发人员可以轻松地为其应用程序提供屏幕共…...
傻瓜式Java操作MySQL数据库备份
文章目录 前言存储数据库存储数据表 前言 数据库备份是开发工作中经常要做的事情,好处是mysql提供了一个非常好的命令 mysqldump,直接调用它就可以将数据以sql文件的形式备份出来。但是直接写命令非常不方便,遇到定时备份或者指定备份那么就需…...
redis常用操作命令
日升时奋斗,日落时自省 注:命令区分有点细,择取自己需要的即可 目录 1、单机架构 2、数据库和应用分离 3、分布式基本概念 3.1、应用(Application)/系统(System) 3.2、模块(Module)/组件&…...
pytorch gpu安装
cuda https://blog.csdn.net/qq_51570094/article/details/124148671 https://blog.csdn.net/zxdd2018/article/details/127705627 cudnn https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html#installlinux-tar 更改cudnn 保证文件目录中只有一个解压后…...
uni跳转页面不缓存上一个页面的方法
一、前言 要实现一个需求,从a页面跳转到b页面,从b页面跳转到c页面,然后按返回,从c页面直接返回a页面(不返回b页面) a->b->c c->a 二、实现方法 前端框架使用的是uni-app,我们修改…...
排序:败者树和置换选择排序(解决外部排序中的优化问题)
1.算法目的(败者树) 解决多路平衡归并带来的问题。 在外部排序中,使用k路平衡归并策略, 选出一个最小元素需要对比关键字(k-1)次, 导致内部归并所需时间增加。(可用“败者树”进行优化) 2.败者树的定义 …...
【超分:光谱响应函数】
Spectral Response Function-Guided Deep Optimization-Driven Network for Spectral Super-Resolution (光谱响应函数引导的深度优化驱动网络光谱超分辨) 高光谱图像(HSI)是许多研究工作的关键。光谱超分辨率(SSR&a…...
IoT 物联网 JavaScript 全栈开发,构建家居环境监控系统实战
智能家居环境监测端到端场景,全栈JavaScript开发,串联Ruff硬件、温湿度和空气质量传感器、阿里云 IoT、Serverless函数计算、百度ECharts可视化、最终以微信小程序形式在微信里实时展示家中实时温度,湿度,PM2.5指数。 01 技术架构…...
jupyter notebook可以打开,但无法打开.ipynb文件,报错500 : Internal Server Error
1、错误信息 2、解决办法 打开Anaconda Promt界面,进入自己的虚拟环境。在命令行输入以下指令: pip install --upgrade nbconvert...
latex图片编号+表格编号
对编号重新自定义 \renewcommand{\thefigure}{数字编号x}重新命名图的编号\renewcommand{\thetable}{数字编号x}重新命名表的编号编号含义 平时看书经常看到“图1.2”这样的编号,含义是第1章的第2幅插图;或者“图1.1.2”,含义是第1章第1节的…...
【1day】用友时空KSOA平台 imagefield接口SQL注入漏洞学习
注:该文章来自作者日常学习笔记,请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与作者无关。 目录...
linux之美
linux系统和window系统区别 Linux和Windows是两个不同的操作系统。Linux是一个开源操作系统,而Windows是一个商业操作系统。 Linux可以访问源代码并根据用户的需求进行修改,而Windows无法访问源代码。 Linux是免费的,而Windows是商业操作系…...
5、超链接标签
5、超链接标签 超链接标签就是我们常说的a标签 <a href"path" target"目标窗口位置">连接文本或图像</a> <!-- href(必填项):连接路径 target:连接在哪个窗口打开?是在新页面打开…...
CCF CSP认证历年题目自练 Day15
CCF CSP认证历年题目自练 Day15 题目一 试题编号: 201709-1 试题名称: 打酱油 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 小明带着N元钱去买酱油。酱油10块钱一瓶,商家进行促销…...
APP的收费模式及特点
移动应用(APP)的收费模式多种多样,可以根据开发者的需求、目标受众和应用的性质来选择。以下是一些常见的APP收费模式及其特点,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎…...
RAG和向量索引
为特定用例设计代理时,需要确保语言模型已建立基础并使用与用户所需内容相关的事实信息。 虽然语言模型针对大量数据进行了训练,但它们可能无权访问你想要向用户提供的知识。 若要确保代理基于特定数据提供准确且特定于域的响应,可使用检索增…...
在线图片处理工具源码, 多功能编辑格式转换HTML单文件版
概述 在数字化内容创作与网站运营的日常中,高效、便捷的图片处理能力是提升工作效率的关键。无论是为了优化网页加载速度而进行的图片压缩,还是为了满足特定设计需求的格式转换与尺寸调整,都离不开得力的工具支持。为此,幽络源源…...
数据库安全与合规:保护你的数据资产
数据库安全与合规:保护你的数据资产 引言 数据库是企业的核心数据资产,数据库安全不仅关系到业务的正常运行,更关系到用户隐私和企业声誉。本文将从访问控制、数据加密、审计日志、备份恢复等多个维度,全面探讨数据库安全与合规的…...
Python 爬虫进阶技巧:本地 Cookies 导入实现免登录爬取
前言 在 Python 爬虫实际开发场景中,大量资讯平台、社交站点、电商后台、个人中心类页面均设置了登录权限校验,未携带有效登录身份标识的请求会直接跳转登录页、返回权限不足提示或拒绝数据响应。常规账号密码模拟登录存在诸多弊端,接口加密、验证码拦截、账号风控封禁、参…...
AI编程技能自学习:构建Claude与Cursor的智能协同开发环境
1. 项目概述:当Claude遇上Cursor,一场关于AI编程技能的自我进化最近在GitHub上看到一个挺有意思的项目,叫Self-Learning-Claude-Skill。虽然项目描述和正文都还是空的,但光看这个标题和关键词——claude-code、cursor、skills——…...
Timoni高级功能揭秘:类型验证、签名和OCI分发
Timoni高级功能揭秘:类型验证、签名和OCI分发 【免费下载链接】timoni Timoni is a package manager for Kubernetes, powered by CUE and inspired by Helm. 项目地址: https://gitcode.com/gh_mirrors/ti/timoni Timoni是一个基于CUE的Kubernetes包管理器&…...
招募Kiro大使!会员权益、内测资格等重磅福利等你领!
亚马逊云科技上线了Kiro社区中心与Kiro Labs,旨在为开发者打造一个发现资源、交流联结、共同成长的专属阵地。目前已有不少开发者主动向项目专区投稿作品、分享活动信息,与众多开发者互帮互助一同成长。现在,亚马逊云科技将社区建设再往前推进…...
Baichuan-7B开源大模型:从环境搭建、推理调优到LoRA微调实战
1. 项目概述:一个值得深入研究的开源大语言模型最近在开源社区里,Baichuan-7B这个名字的讨论热度一直不低。作为一个长期关注大模型技术动向的从业者,我自然也对它进行了一番深入的“把玩”和研究。简单来说,Baichuan-7B是由百川智…...
冬日狂想曲(赠去马赛克补丁)2026.5.13最新版免费下载 转存后自动更新 (看到请立即转存 资源随时失效)pc手机版通用
下载链接 冬日狂想曲》(Winter Memories)作为《夏日狂想曲》的正统续作,在独立游戏圈、尤其是像素风生活模拟(Life Sim)领域有着极高的讨论度。 针对你提到的内容,我需要先说明:作为一个人工智…...
从无人机悬停到电机调速:深入浅出聊聊‘稳定裕度’到底在保证什么?
从无人机悬停到电机调速:稳定裕度如何守护工程系统的安全边界 当无人机在强风中突然失控摇摆,或是工业机械臂在高速运动时出现震颤,这些现象背后往往隐藏着一个关键控制参数——稳定裕度。对于工程师而言,它不仅是教科书上的数学概…...





