栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【c语言】动态内存管理

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【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 
#include 
#include 
#include 
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 
#include 
#include 
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 
#include 
#include 
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 
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 
#include 
#include 
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 
#include 
struct s
{
	int i;
	int a[];
};

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/954550.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号