动态内存管理(2)

练习:

1.代码能否正常运行

 显然不能

 错误1:str 是char*类型的指针,传参给GetMemory函数,函数同样用char*类型的指针接收(传值调用,传的是变量本身),此时的 p 为形参,是实参 str 的一份临时拷贝,函数为 p 开辟了一块动态内存空间,但改变形参不会影响实参,因此当函数返回时, str 仍是空指针,不可能将字符串拷贝到空指针

错误2:申请了动态内存空间之后没有释放内存,会发生内存泄漏,函数结束指针p就被销毁了,无法再释放空间

 解决方法:

 函数参数传地址,用二级指针接收;使用完毕释放空间

2.代码能否正常运行

 不能

用 str 指针接收函数中创建的字符串的地址,但是当函数返回时,字符串的空间就被销毁了,此时指向字符串的 str 就成了野指针,对野指针解引用会导致非法访问

 有特殊情况:

 当函数返回时,函数内部开辟的空间还没有立刻被销毁,此时解引用访问仍能成功

但如果函数返回后,在main函数上开辟了新的栈帧,新的栈帧会覆盖还未被完全销毁的空间,就不能再访问该空间了

3.代码能否正常运行

 问题仅在于忘记释放空间,改正:

 4.代码能否正常运行

 问题:释放内存过后应该及时置空

重点:C/C++程序的内存开辟

内存区域划分:

 静态变量和全局变量都放在数据段;局部变量,数组放在栈区;常量放在代码段;

malloc,realloc,calloc创建的动态内存空间都放在堆区。

柔性数组

柔性数组就是结构体中,最后一个元素为大小不确定的数组

写法:

 柔性数组之前必须有一个结构体成员

实现:代码1

//柔性数组
struct S
{
    int n;
    int arr[0];//柔性数组
};
int main()
{
    struct S* ps = (struct S*)malloc(sizeof(struct S) + 40);//40个字节是给柔性数组的
    if (ps == NULL)
    {
        perror("malloc");
        return 1;
    }
    ps->n = 100;
    int i = 0;
    for (i = 0; i < 10; i++)//10个整型
    {
        ps->arr[i] = i + 1;//给柔性数组赋值
    }
    //如果觉得空间不够,可以用realloc扩容
    struct S* ptr=realloc(ps, sizeof(struct S) + 60);
    //先拷贝一份判断判断是否扩容成功
    if (ptr == NULL)//扩容失败
    {
        perror("realloc");
        return 1;
    }
    //扩容成功
        ps = ptr;
        ps->n = 15;
        for (i = 0; i < 15; i++)
        {
            printf("%d\n", ps->arr[i]);
        }
    //释放
    free(ps);
    ps = NULL;

    return 0;
}

 当需要结构体的一个数组大小是可变化的,就用柔性数组

但是我们不使用柔性数组也能实现柔性数组的功能,例如代码2:

//不使用柔性数组实现柔性数组的功能
struct S
{
	int n;
	int* arr;
};
int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S));
	ps->n = 100;
	ps->arr = (int*)malloc(40);//1 2 3 4 5 6 7 8 9 10
	if (ps->arr== NULL)
	{
		perror("malloc");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		ps->arr[i] = i + 1;
	}
	//扩容
	int* ptr = (int*)realloc(ps->arr, 60);
	if (ptr == NULL)
	{
		perror("realloc");
		return 1;
	}
	else
	{
		ps->arr = ptr;
	}
	//打印
	for (i = 0; i < 15; i++)
	{
		printf("%d\n", ps->arr[i]);
	}
	//释放
	free(ps);
	ps = NULL;
}

区别是代码1柔性数组只用开辟一次动态内存,而代码2需要多次,多次开辟空间不利于对内存碎片的利用

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值