c语言 动态内存分配 柔性数组

news2024/11/15 10:27:42

常见的动态内存错误

对null指针的解引用操作

int main()//错误1  因为没有判断
{
	int* p = (int*)malloc(10000);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}
	return 0;
}

对动态开辟空间的越界访问

int main()
{
	int* p = malloc(10 * sizeof(int));
	if (p == NULL)
	{
		return 1;
	}
	int i = 0;

	for (i = 0; i < 40; i++)  
	{
		*(p+i) = i;
	}
	
	free(p);
	p = NULL;

	return 0;
}

开辟10个却要访问40个

使用free释放非动态开辟的空间

int main()
{
	int arr[10] = { 0 };//栈区
	int* p = arr;
	//使用
	
	free(p);//使用free释放非动态开辟的空间
	p = NULL;

	return 0;
}

使用free释放动态内存中的一部分


int main()
{
	int* p = malloc(10 * sizeof(int));
	if (p == NULL)
	{
		return 1;
	}
	int i = 0;

	for (i = 0; i < 5; i++)
	{
		*p++ = i;
	}
	
	free(p);
	p = NULL;

	return 0;
}

在这里插入图片描述
p释放的时候释放的是后面的一部分,p++一直在走没人记得这块空间的起始位置

对同一块动态开辟的空间,多次释放

就是使用两次或多次free 释放完后传空指针 下次在释放free(null)什么也不会发生

动态开辟的空间忘记释放- 内存泄漏 - 比较严重的

void test()
{
	int* p = (int*)malloc(100);
	if (p == NULL)
	{
		return;
	}
	//使用
}//没有置null p出了这块空间会销毁 但是malloc不会。malloc只能主动释放  或者程序结束

int main()
{
	test();
	//....
	return 0;
}

#include <string.h>
//
//str传给GetMemory函数的时候是值传递,所以GetMemory函数的形参p是str的一份临时拷贝。
//在GetMemory函数内部动态申请空间的地址,存放在p中,不会影响外边str,所以当GetMemory函数返回之后,str依然是NULL。所以strcpy会失败。
//
//当GetMemory函数返回之后,形参p销毁,使得动态开辟的100个字节存在内存泄漏。无法释放。
void GetMemory(char* p)//传过来后p也变空指针
{
	p = (char*)malloc(100);//p来维护开辟的100.调用完出去p销毁(p是临时变量)。开辟空间找不到导致内存泄漏
}
void Test(void)
{
	char* str = NULL;
	GetMemory(str);//值传递 没有传递地址
	strcpy(str, "hello world");
	printf(str);
}

int main()
{
	Test();
	return 0;
}//运行不出结果

进行修改后让代码运行

//改:1
char* GetMemory(char* p)
{
	p = (char*)malloc(100);
	return p;
}
void Test(void)
{
	char* str = NULL;
	str = GetMemory(str);
	strcpy(str, "hello world");
	printf(str);//?
	//printf("hello world");//char *p = "hello world";
	free(str);
	str = NULL;
}
int main()
{
	Test();
	return 0;
}

改2

void GetMemory(char** p)
{
	*p = (char*)malloc(100);
}
void Test(void)
{
	char* str = NULL;
	GetMemory(&str);

	strcpy(str, "hello world");
	printf(str);
	free(str);
	str = NULL;
}

int main()
{
	Test();
	return 0;
}

题2

//GetMemory 函数内部创建的数组是在栈区上创建的
//出了函数,p数组的空间就还给了操作系统
//返回的地址是没有实际的意义,如果通过返回的地址,去访问内存就是非法访问内存的
//
char* GetMemory(void)
{
	char p[] = "hello world";  //hello world\0
	return p;//临时变量的创建出函数销毁。但是也会返回返回的是地址编号 出栈销毁  但是堆不会
}
void Test(void)
{
	char* str = NULL;
	str = GetMemory();
	printf(str);
}

int main()
{
	Test();
	return 0;
}//运行结果出错

题3

void GetMemory(char** p, int num)
{
	*p = (char*)malloc(num);
}
void Test(void)
{
	char* str = NULL;
	GetMemory(&str, 100);
	strcpy(str, "hello");
	printf(str);
	//free(str);
	//str = NULL;少了指针释放
}

int main()
{
	Test();
	return 0;
}

题4

void Test(void)
{
	char* str = (char*)malloc(100);
	strcpy(str, "hello");
	free(str);//非法访问内存空间,str指向的动态内存空间已经被释放了
	//str = NULL;  记得加上加上这句

	if (str != NULL)
	{
		strcpy(str, "world");
		printf(str);
	}
}

int main()
{
	Test();
	return 0;
}

c/c++程序的内存开辟

在这里插入图片描述
在这里插入图片描述
临时数据用完就回收的放在栈区上
在这里插入图片描述

柔性数组

在这里插入图片描述

struct S
{
	int n;
	int arr[];//大小是未知
};

struct S
{
	int n;//4
	int arr[0];//大小是未知
};  以上两种都可以

柔性数组的特点

在这里插入图片描述

struct S
{
	int n;//4
	int arr[0];//大小是未知
};
int main()
{
	struct S s = {0};
	printf("%d\n", sizeof(s));//?

	return 0;
}//结果为4

3

int main()
{
	//期望arr的大小是10个整形
	struct S*ps = (struct S*)malloc(sizeof(struct S)+10*sizeof(int));//sizeof(struct S) 计算出柔性数组前的大小 后面加的是柔性数组的大小
	ps->n = 10;
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		ps->arr[i] = i;
	}
	//增加
	struct S* ptr = (struct S*)realloc(ps, sizeof(struct S)+20*sizeof(int));
	if (ptr != NULL)
	{
		ps = ptr;
	}
	//使用
	
	//释放
	free(ps);
	ps = NULL;

//同上相比这一样可以实现 但是效率不高 并且容易出错  这就是柔性数组的优势
struct S
{
	int n;
	int* arr;
};

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S));
	if (ps == NULL)
		return 1;
	ps->n = 10;
	ps->arr = (int*)malloc(10*sizeof(int));
	if (ps->arr == NULL)
		return 1;
	
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		ps->arr[i] = i;
	}
	//增加
	int*ptr = realloc(ps->arr, 20 * sizeof(int));
	if (ptr != NULL)
	{
		ps->arr = ptr;
	}
	//使用
	
	//释放
	free(ps->arr);
	ps->arr = NULL;
	free(ps);
	ps = NULL;

	return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/141583.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5G NR标准: 第16章 初始接入

第16章 初始接入 在 NR 中&#xff0c;初始接入功能包括&#xff1a; • 设备在进入系统覆盖区域时最初找到小区的功能和过程。 • 处于空闲/非活动状态的设备访问网络的功能和程序&#xff0c;通常是请求建立连接&#xff0c;通常称为随机访问。 在相当大的程度上&#xff0…

ORA-27102:out of memory Linux-x86_64 Error: 12: Cannot allocate memory

一 问题描述 无法启动数据库&#xff0c;报错&#xff1a; 二 排查思路 1.确保sga_target,sga_max_size比可用物理内存小 2.检查kernel.shmmax&#xff0c;kernel.shmall是否设置得太小 一般出现ORA-27102&#xff1a;out of memory&#xff0c;是/etc/sysctl.conf种内核参…

Apache Tomcat 存在 JsonErrorReportValve 注入漏洞(CVE-2022-45143)

漏洞描述 Apache Zeppelin是一款基于 Web 可实现交互式数据分析的notebook产品。 在Apache Zeppelin 0.10.1及以前的版本中“Move folder to Trash”功能存在路径遍历漏洞&#xff0c;由于未对InterpreterSettingManager类remove方法中id参数进行正确校验&#xff0c;攻击者可…

看完这篇文章,我再也不用担心线上出现 CPU 性能问题了(上)

目录CPU 使用率平均负载进程上下文切换总结生产环境上出现 CPU 性能问题是非常典型的一类问题&#xff0c;往往这个时候就比较考验相关人员排查问题的能力我相信不少小伙伴在工作当中多多少少都会碰到 CPU 出现性能瓶颈 不知道小伙伴们有没有跟我一样的感受——当 CPU 出现性能…

小红书排行榜 | 粉丝增量500w+,探寻爆款种草内容密码

随着兔年来临&#xff0c;回首上个月小红书母婴动态&#xff0c;行业热度依旧高涨&#xff0c;越来越多的达人和新品牌都涌入了小红书&#xff0c;母婴品牌要如何巧用小红书数据分析工具抢占用户心智&#xff1f;增量500w&#xff0b;的母婴博主有何亮点之处&#xff1f;和我一…

【甘特图软件部件】上海道宁与​DlhSoft助力您的Windows与移动应用程序开发

DlhSoft支持 使用可自定义的甘特图 时间轴、项目调度、资源负载图表、 看板、PERT图表和网络图 为您的WPF、ASP .NET、JavaScript 或macOS和iOS应用程序 设计更智能的应用程序 DlhSoft提供了 真正强大的甘特图软件部件 Apple平台开发人员可以 轻松地将其集成到 他们自…

equals和 == 的区别

1 问题equals和 都可以对于值类型&#xff0c;然后比较代数值是否相等。那么equals和 的具体区别是什么&#xff1f;2 方法 是运算符&#xff0c;可以使用在基本数据类型变量和引用数据类型变量中&#xff0c;如果比较的是基本数据类型&#xff1a;比较的是两个变量保存额数据…

嵌入式实时操作系统的设计与开发(二)

加载应用程序与创建程序运行环境 将应用程序从Flash加载到RAM的实现代码是一定在启动代码中的。 计算机系统的运行其实是CPU到相应的内存地址去取回指令&#xff0c;然后译码并执行指令&#xff0c;再依次从下一个地址取指、执行&#xff0c;而程序就是指令与数据的集合。 程序…

JAVAWeb开发(基于分片的网络状态查询方法、装置及存储介质)

本文基于分片的网络状态查询方法、装置及存储介质已是申请的专利。本人为第一发明人&#xff0c;这里给出来是提供一种写专利的范本&#xff0c;仅供参考。专利申请号&#xff1a;CN202110346967.5正文部分&#xff1a;技术领域本申请涉及但不限于计算机网络数据传输一致性领域…

opencv--颜色物体追踪 图片的形态学处理函数

目录 一、主要函数介绍 1. cv2.erode() 2. cv2.dilate() 3. cv2.findContours() 4. cv2.circle() 5. cv2.line() 二、代码 这里首先确定是否安装imutils库&#xff0c;这个库能让调整大小或者翻转屏幕等基本任务更加容易实现。这一次主要应用的是对于图片的形态学处理函…

【Android春招】Android基础day1

一、填空题 1&#xff0e;Android是基于__ 的移动端开源操作系统。 Linux 2&#xff0e;Android系统是由__公司推出的。 谷歌 3&#xff0e;Android 11对应的API编号是__。 30 4&#xff0e;App除了在手机上运行&#xff0c;还能在电脑的__上运行。 模拟器&#xff08;AVD&…

测试之概念篇【需求、测试用例、Bug描述、产品的生命周期、开发模型、测试模型】

文章目录1. 什么是需求2. 测试用例是什么3. Bug 是描述4. 产品的生命周期5. 软件测试贯穿于软件的整个生命&#xff0c;如何贯穿&#xff1f;6. 开发模型&#xff08;瀑布模型、螺旋模型、增量模型和迭代模型、敏捷模型&#xff09;7. 测试模型&#xff08;V模型、W模型&#x…

【Java寒假打卡】Java基础-BigDecimal

【Java寒假打卡】Java基础-BigDecimal构造方法四则运算BigDecimal的特殊方法基本数据类型包装类自动装箱与自动拆箱Integer的类型转换将数字字符串进行拆分成整数数组构造方法 package com.hfut.edu.test1;import java.math.BigDecimal;public class test3 {public static void…

Crontab命令详解

crontab命令是Unix和Linux用于设置周期性被执行的指令&#xff0c;是互联网很常用的技术&#xff0c;很多任务都会设置在crontab循环执行。crontab命令可以精确到分&#xff08;精确到秒的一般写脚本&#xff09;&#xff0c;相当于闹钟。 如果不使用crontab&#xff0c;那么任…

GD32F103-TIMER模块

定时器是一个功能强大的外设。 一般功能&#xff1a; 定时中断&#xff0c;计时器&#xff0c;给定一个时间&#xff0c;到达时间后产生一个中断定时器输出比较的功能&#xff0c;用于PWM波形的产生&#xff0c;驱动电机定时器输入捕获&#xff0c;测频率 核心关键参数&#…

基于Java+SpringBoot+vue+element实现新冠疫情物资管理系统详细设计

基于JavaSpringBootvueelement实现新冠疫情物资管理系统详细设计 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 欢迎点赞 收藏 ⭐留言 文末获取源码联系方式 文章目录基于…

文件IO----(open、close、read、write、lseek)

1.文件IO 介绍:&#xff08;系统IO、系统调用&#xff09; POSIX&#xff08;可移植操作系统接口&#xff09;定义的一组函数&#xff0c;不提供缓冲机制&#xff0c;每次读写操作都引起系统调用&#xff0c;核心概念是文件描述符&#xff0c;访问各种文件类型&#xff0c;Lin…

Keychron 键盘指南

文章目录QQ1Q2Q3Q4Q5KK1K2k3 && k3proK3 VS K7k6 && K6prok7K8k10K12K14CVV1V2V3V4V5V6SQ Q1 Q1 是一款革命性的全金属键盘&#xff0c;每个开关、键帽、稳定器、旋钮甚至面板都具有可定制的功能。它专为个性化体验和卓越的打字舒适度而设计。 双垫片设计…

Cadence PCB仿真使用Allegro PCB SI配置仿真库的方法图文教程

⏪《上一篇》   🏡《总目录》   ⏩《下一篇》 目录 1,概述2,配置方法3,总结1,概述 本文简单介绍使用Allegro PCB SI软件选择需要仿真的网络的方法。 2,配置方法 第1步:打开待仿真的PCB文件,并确认软件为Allegro PCB SI 如果,打开软件不是Allegro PCB SI则可这样…

模型微调,低预算,高期望!

作为迁移学习中的常用技术&#xff0c;Fine-tuning&#xff08;微调&#xff09;已经成为了深度学习革命的重要部分。微调不需要针对新任务从头开始学习&#xff0c;只需要加载预训练模型的参数&#xff0c;然后利用新任务的数据进行一步训练模型即可。也可以说微调是对开放域任…