【c语言】动态内存管理

在创建数组的时候,我们必须提前指定数组大小,那就会存在开辟空间过大或者过小的问题,所以需要用到内存管理。


1、malloc

void* malloc(size_t size);

申请一片size字节大小的空间,返回一个指针,这个指针指向的是这片内存空间的起始位置,如果没有申请成功就返回NULL。

2、calloc

void* calloc(size_t num,size_t size);

开辟num个元素的空间,每个元素的大小是size字节,并且初始化为0.

如果成功返回开辟空间的起始地址,否者返回NULL

3、realloc

void* realloc (void* ptr, size_t size);

修改ptr指向的内存空间的大小,当ptr为NULL时返回realloc的功能和malloc一样。

如果成功返回起始位置的地址,如果失败返回NULL。

在realloc重新开辟空间的过程中,有可能在原有空间上接一个空间,也有可能从新开辟一个空间。

使用realloc的时候需要注意,如果空间增容不成功会返回NULL,会把原来的空间覆盖掉,所以最好不要直接将realloc的返回值赋给原来的指针。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{
	int* str = (int*)malloc(3 * sizeof(int));
	if (NULL == str)//开辟不成功
	{
		printf("%s", strerror(errno));
		return 0;
	}
	int* temp = (int*)realloc(str, 5 * sizeof(int));
	if (NULL != temp)
	{
		str = temp;
        temp = NULL;
	}
	free(str);
    str = NULL;

	return 0;
}

4、free

将开辟的空间释放掉,free后记得将指针设为NULL

5、常见错误

1.对NULL指针的解引用操作

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

3.对非动态开辟内存使用free释放

4.使用free释放一块动态开辟内存的一部分(一般情况下不要修改返回指针所指向的位置)

5.对同一块动态内存多次释放

6.动态内存开辟的空间忘记释放(内存泄漏)

6、经典笔试题

1.

#include <stdio.h>
#include <string.h>
#include <memory.h>
void GetMemory(char* p)
{
	p = (char*)malloc(100);
}
void test()
{
	char* str = NULL;
	GetMemory(str);
	strcpy(str, "hello,world");
	printf(str);
}
int main()
{
	test();
	return 0;
}

1.p没有释放会造成内存泄漏

2.p是str的临时拷贝,因此对p的修改不会影响到str,所以str仍是NULL,对空指针使用strcpy函数会时程序崩溃。

如果想达到预期的效果可以传地址

#include <stdio.h>
#include <string.h>
#include <memory.h>
void GetMemory(char** p)
{
	*p = (char*)malloc(100);
}
void test()
{
	char* str = NULL;
	GetMemory(&str);
	strcpy(str, "hello,world");
	printf(str);
	free(str);
}
int main()
{
	test();
	return 0;
}

 2.

#include <stdio.h>
char* GetMemory()
{
	char p[] = "hello world";
	return p;
}
void test()
{
	char* str = NULL;
	str = GetMemory();
	printf(str);
}
int main()
{
	test();
	return 0;
}

在GetMemory函数中创建了字符数组p,返回的是字符数组首元素的地址,但是内存空间已经被操作系统释放了,因此通过str去访问那片空间读到的是不确定的值

3.

#include <stdio.h>
#include <string.h>
#include <memory.h>
void test()
{
	char* str = (char*)malloc(100);
	strcpy(str, "hello");
	free(str);
	if (str != NULL)
	{
		strcpy(str, "world");
		printf(str);
	}
}
int main()
{
	test();
	return 0;
}

str已经释放了,但是没有置空,会造成非法访问

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

8、柔性数组

在c99中,结构体中的最后一个元素允许是未知大小的数组,这叫做柔性数组成员

struct s
{
	int i;
	int a[];
};
//或者
struct s
{
	int i;
	int a[0];
};

 柔性数组的特点:

结构中的柔性数组成员前面必须至少一个其他成员。

sizeof返回的这种结构大小不包括柔性数组的内存

包含柔性数组成员的结构用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

#include <stdio.h>
#include <stdlib.h>
struct s
{
	int i;
	int a[];
};

int main()
{
	struct s* ps = (struct s*)malloc(sizeof(struct s) + 40);//int a[10]
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值