动态内存管理

本文介绍了动态内存管理的基础概念,包括malloc、free、calloc和realloc等函数的使用方法及注意事项。此外,还探讨了常见的内存错误及其避免策略。

目录

动态内存存在的原因:

动态内存函数:

1.malloc(要和free搭配使用)

2.free(释放函数)

3.calloc(也要和free搭配使用)

3.realloc

 常见内存错误:

1.段错误

2.内存错误注意点:

3.野指针:

4.多次free内存块,是会导致程序崩溃的


动态内存存在的原因:

int val=20;
char arr[10]={0};

(1)在栈空间上开辟四个字节

(2)在栈空间上开辟10个字节的连续空间

其特点:1.空间开辟大小是固定的

               2.数组在申明的时候,必须指定数组的长度,它需要的内存在编译时分配

(对于空间的需求,不仅仅是上述的情况,有时候我们需要的空间大小在程序运行的时候才能知道,那数组的编译时开辟空间的方式就不能满足了,就需要动态内存)

动态内存函数:

1.malloc(要和free搭配使用)

(无需初始化)

void* malloc (size_t size)

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

1.如果开辟成功,则返回一个指向开辟好空间指针

2.如果开辟失败,则返回一个NALL指针,因此malloc的返回值一定要检查。

3.返回值的类型是void*,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。

4.如果参数size为0,malloc的行为是标准是未定义的,取决于编译器。

int main()
{
    int *p=(int*)malloc(40);
    return 0;
}
#include<stdio.h>
#include<errno.h>
#include<string.h>

int main()
{
    int *p=(int*)malloc(40);
    if(p==NULL)//如果空间不够,报错
    {
        printf("%s\n",strerror(errno));
        return 0;
    }
    
    int i=0;
    for(i=0;i<10;i++)
    {
        *p=i;
        p++;
    }

 

(栈区:局部变量        堆区:动态内存分配)

2.free(释放函数)

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

1.如果ptr指向的空间不是动态开辟,那free函数的行为是未定义的。

# include < stdio . h >
# include < errno.h >
# include < string.h >
int main ()
{
int * p = (int *) malloc (40);
if(p==NULL)//如果空间不够,报错
{
printf (" % s \ n ", strerror (errno));
返回0;
}
int i = 0;
(i= 0;i< 10;i+ +)
{
* p =i;
p + +;
}
​free(p);
p=NULL;
return 0;

3.calloc(也要和free搭配使用)

(需要初始化)

int main()
{
int *p=(int*)calloc(10,sizeof(int));
if(p==NULL)
{
perror("calloc");
return 1;
}
int i=0;
for(i=0;i<10;i++)
{
*(p+1)=i;
}
//释放
free(p);
p=NULL;
return 0;
}

3.realloc

realloc函数的出现让动态内存管理更加灵活

有时会让我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大,为了合理的申请内存,我们一定会对内存的大小做灵活的调控,那realloc函数就可以做到对动态开辟内存大小的调整

void realloc(void* ptr,size_t size);
int* p=(int*)malloc(40);
if(p==NULL)
return 1;
int i=0;
for(i-0;i<10;i++)
{

*(p+1)=i;
}
for(i-0;i<10;i++)
{
printf("%d",*(p+1));
}

int *ptr=(int* )realloc(p,80);
if(ptr!=NULL)
{
p=ptr;
}
//...
free(p)
p=NULL;

int main()
{
int * p=(int*)malloc(40);
if(p==NULL)
return 1;
int i=0;
for(i=0;i<10;i++)
{
*(p+1)=i;
}
for(i=0;i<10;i++)
{
printf("%d ",*(p+i));
}
int * ptr=(int*)realloc(p,80);
if(ptr!=NULL)
{
p=ptr;
ptr=NULL;
}


ptr是要调整的内存地址

size调整之后新大小

返回值为调整之后的内存起始位置

这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间

realloc在调整内存空间的是存在两种情况:(1)原有空间之后有足够大的空间

                                                                     (2)原有空间之后没有足够大的空间

 常见内存错误:

1.段错误

使用未分配成功的内存

避免方式:在使用内存之前检查指针是否为NULL;

                引用分配成功但尚未初始化内存

避免方式:赋予初值,即使便是赋予零值也不可省略

                内存分配成功并且已经初始化,但操作越过内存的边界

避免:注意下表的使用不能超出边界

        忘记释放内存,造成内存泄漏

避免方式:申请内存的方式和释放内存的方式需要成双成对

                释放内存之后却继续去使用这一块内存

避免方式:使用free内存之后,把指针置为NULL;

2.内存错误注意点:

指针消亡了,并不表示它所☞的内存会被自动释放,(在free之前,直接将指针为NULL);

内存释放了,并不代表指针会消亡或者成了NULL指针;(在free之后,指针并没有进行NULL设置)

3.野指针:

野指针的形成是指针变量没有被初始化,任何指针变量刚被创建的时候不会自动成为NULL指针,它的缺省值是最忌的,它会乱指一气

指针变量在创建的同时应当被初始化,要么将指针设置为NULL,也会出现“野指针”,它是指向“垃圾”内存的指针

4.多次free内存块,是会导致程序崩溃的

P2911 [USACO08OCT] Bovine Bones G 是洛谷【入门 4】数组中的一道题目。题目描述为 Bessie 喜欢棋盘游戏和角色扮演游戏,她说服 Farmer John 带她去一家爱好商店,在那里她购买了三个骰子用于投掷,这些骰子分别有 S1、S2 和 S3 个面[^1]。 在解题代码方面,有 Java 和 C++ 两种实现。Java 代码通过定义一个长度为 81 的数组统计不同和值出现的次数,通过嵌套循环模拟掷骰子的过程,将每个和值对应的数组元素加 1,同时更新最大出现次数及其对应的和值,最后输出最大出现次数对应的和值[^2]。示例代码如下: ```java import java.util.Scanner; public class P2911_1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int s1 = sc.nextInt(), s2 = sc.nextInt(), s3 = sc.nextInt(); int[] arr = new int[81]; int max = 0; int temp = 0; for (int i = 1; i <= s1; i++) { for (int j = 1; j <= s2; j++) { for (int k = 1; k <= s3; k++) { arr[i + j + k]++; if (temp < arr[i + j + k]) { max = i + j + k; temp = arr[i + j + k]; } } } } System.out.println(max); sc.close(); } } ``` C++ 代码同样使用数组统计和值出现的次数,先通过三重循环模拟掷骰子得到所有可能的和值并更新对应次数,再遍历所有可能的和值范围,找出出现次数最多且和值最小的结果并输出[^3]。示例代码如下: ```cpp #include<bits/stdc++.h> using namespace std; int s1, s2, s3, res; int cnt[20000]; int maxn = -1e9; int main() { scanf("%d%d%d", &s1, &s2, &s3); for (int i = 1; i <= s1; ++i) { for (int j = 1; j <= s2; ++j) { for (int k = 1; k <= s3; ++k) { cnt[i + j + k]++; } } } for (int i = 3; i <= s1 + s2 + s3; ++i) { if (cnt[i] > maxn) maxn = cnt[i], res = i; } printf("%d", res); return 0; } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值