草庐IT

【C语言跬步积累】——动态内存管理

PH_modest 2023-10-24 原文

🌏博客主页:PH_modest的博客主页
🚩当前专栏:C语言跬步积累
💌其他专栏:
🔴 每日一题
🟡 每日反刍
🟢 读书笔记
🌈座右铭:广积粮,缓称王!

一.malloc和free

1.malloc

void* malloc(size_t size);

这个函数向内存申请一块连续可用 的空间,并返回指向这块空间的指针。

  • 如果开辟成功,则返回一个指向开辟好空间的指针
  • 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。( 使用strerror(errno) 来获取错误信息 )
  • 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。 (强制类型转换
  • 如果参数 size为0,malloc的行为是标准是未定义的,取决于编译器
  • 申请空间的大小是以字节为单位

2.free

void free(void* ptr);

free函数用来释放动态开辟的内存。

  • 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
  • 如果参数 ptr 是NULL指针,则函数什么事都不做。
  • free并不会主动将接收的地址置为空,释放之后需要主动将地址置为空(即free(p); p = NULL;

3.应用

#include<stdio.h>
#include<string.h>//strerror的头文件
#include<stdlib.h>//malloc的头文件
#include<errno.h>//errno的头文件
int main()
{
	//申请
	int* p = (int*) malloc(20);
	if(*p == NULL)//申请内存空间太大的话会返回空指针
 	{
		printf("%s\n",strerror(errno));//反馈错误内容
		return 1;
 	}
 	//使用
 	int i = 0;
 	for(i = 0; i < 5; i ++)
 	{
 		p[i] = i + 1;
 		//*(p + i) = i + 1;
 		
 	}
 	for(i = 0; i < 5; i++)
 	{
 		printf("%d ",p[i]);
 	}
	//释放
	free(p);//释放p的内存
	p=NULL;//将p的内存置为空
	return 0;
}

二.calloc

void* calloc(size_t num, size_t size);
  • 函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0
  • 与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。

1.应用

#include<stdio.h>
#include<errno.h>
#include<string.h>
#include<stdlib.h>

int main()
{
	//申请
	int *arr = (int*)calloc(20, sizeof(int));
	if (arr == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	//使用
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		*(arr + i) = i + 1;
	}
	for (i = 0; i < 5; i++)
	{
		printf("%d ", arr[i]);
	}
	//释放
	free(arr);
	arr = NULL;
	return 0;
}

2.calloc和malloc之间的特点

  • 参数不同
  • 都是在堆区上申请内存空间,但malloc不会将内存空间初始化为0,calloc会初始化为0,如果需要初始化为0就用calloc
  • 申请的内存是以字节为单位

三.realloc

1.知识点

void* realloc(void* ptr,size_t size);
  • ptr是要调整的内存地址
  • size 是调整之后新的大小
  • 返回值为调整之后的内存起始位置
  • 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间
  • realloc在调整内存空间的是存在两种情况:
    ①原有空间之后有足够大的空间:该情况要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化
    ②原有空间之后没有足够大的空间:该情况的扩展方法是,在堆空间上另外找一个合适大小的连续空间来使用,这样函数返回的是一个新的内存地址

2.原理

  1. realloc会找一个更大的空间
  2. 将原来的数据拷贝到新空间内
  3. 释放旧空间
  4. 返回新空间的地址

注意

  1. ①中返回的是旧的地址二;②中返回的是新地址,使用realloc前后返回的地址不同
  2. realloc申请空间失败的话会返回空指针

3.应用

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>

int main()
{
	//申请
	int* p = (int*)malloc(20);
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
	}
	//使用
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		p[i] = i + 1;
	}
	//申请空间
	int* str = (int*)realloc(p, 40);
	if (str != NULL)
	{
		p = str;
	}
	//使用
	for (i = 5; i < 10; i++)
	{
		p[i] = i + 1;
	}
	//释放
	free(p);
	p = NULL;
	return 0;
}

最后

本篇简单介绍了动态内存开辟需要用到的函数,下一篇会讲解动态内存中常见的错误,喜欢本专栏的可以点个订阅,让我们一起进步!

有关【C语言跬步积累】——动态内存管理的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby - i18n Assets 管理/翻译 UI - 2

    我正在使用i18n从头开始​​构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在ruby​​onrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi

  3. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  4. ruby-on-rails - Ruby 中的内存模型 - 2

    ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序

  5. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  6. ruby-on-rails - 获取 inf-ruby 以使用 ruby​​ 版本管理器 (rvm) - 2

    我安装了ruby​​版本管理器,并将RVM安装的ruby​​实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby​​。有没有办法让emacs像shell一样尊重ruby​​的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el

  7. ruby-on-rails - 事件管理员日期过滤器日期格式自定义 - 2

    是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s

  8. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  9. 7个大一C语言必学的程序 / C语言经典代码大全 - 2

    嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来

  10. ruby - (Ruby || Python) 窗口管理器 - 2

    我想用这两种语言中的任何一种(最好是ruby​​)制作一个窗口管理器。老实说,除了我需要加载某种X模块外,我不知道从哪里开始。因此,如果有人有线索,如果您能指出正确的方向,那就太好了。谢谢 最佳答案 XCB,X的下一代API使用XML格式定义X协议(protocol),并使用脚本生成特定语言绑定(bind)。它在概念上与SWIG类似,只是它描述的不是CAPI,而是X协议(protocol)。目前,C和Python存在绑定(bind)。理论上,Ruby端口只是编写一个从XML协议(protocol)定义语言到Ruby的翻译器的问题。生

随机推荐