C语言动态内存管理

目录

引言:

为什么进行动态内存管理

二、有关动态内存管理的库函数

2.1 malloc

2.2 calloc

2.3 ralloc

realloc可能会改变内存块的位置

2.4 free

三、有关动态内存管理容易出现的问题

3.1 对NULL指针进行解引用操作

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

3.3 对于非动态内存进行free

3.4  动态开辟内存忘记释放( 内存泄漏 )


C语言动态内存管理是指在程序运行时,根据需要动态地分配和释放内存空间。这种管理方式相比于静态内存管理具有更高的灵活性和效率。

引言:

为什么进行动态内存管理

C语言动态内存管理是指在程序运行时,根据需要动态地分配和释放内存空间。这种管理方式相比于静态内存管理具有更高的灵活性和效率。

  • 允许程序运行或停止时分配和释放内存。
  • 处理不确定大小的数据。
  • 提高程序的灵活性和可延展性。

二、有关动态内存管理的库函数

2.1 malloc

  • malloc(): 用于在堆区分配一块指定大小的内存空间。如果分配成功,它返回一个指向分配区域的指针;如果分配失败,则返回 NULL

函数原型:

void* malloc (size_t size);

按照malloc函数的特点我们可以检测函数内存是否开辟成功,通过检测返回指针类型:

int *ptr = (int *)malloc(sizeof(int));
if (ptr == NULL) {
    perror("malloc");
}

注意:

  • 在使用动态内存分配后,应该始终检查返回的指针是否为NULL或空指针,以确保内存分配成功。
  • 如果分配失败,应适当处理,释放掉已经分配的内存。

2.2 calloc

  • calloc(): 类似于 malloc(), 但它会将分配的内存空间初始化为。它接受两个参数:元素的数量和每个元素的大小

函数原型:

void* calloc (size_t num, size_t size);

运用calloc ( ) 时候,也是要进行返回值检测:

int *ptr = (int *)calloc(sizeof(int));
if (ptr == NULL) {
    perror("calloc");
}

2.3 ralloc

  • realloc(): 用于调整已分配内存块的大小。它接受两个参数:原有内存块的指针和新的大小。如果成功,它返回一个指向新内存块的指针;如果失败,它保留原有内存块并返回 NULL

函数原型:

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

同malloc()和calloc()一样,ralloc()也要进行返回值检测:

int* ptr1 = (int*)realloc(ptr,sizeof(int));
if (ptr1 == NULL){
    perror(realloc);
}
  • ptr是指向已分配内存块的指针.
  • size是新的内存块大小(以字节为单位)。
realloc可能会改变内存块的位置
  1. 当你尝试通过realloc来增大一个内存块的大小时,如果当前内存块后面有足够的连续空间,realloc会简单地扩大这块内存,并返回原来的指针。
  2. 如果当前内存块后面的空间不足以满足新的大小要求,realloc会在堆内存中寻找一个更大的连续空间,将原有数据复制到新的位置,然后释放原来的内存块,并返回新内存块的地址。

2.4 free

  • free():用于释放由malloc()分配的内存空间,接受一个指向要释放内存的指针作为参数.

函数原型:

void free (void* ptr);
  • 只有通过malloccalloc, 或 realloc等函数分配的内存空间才能被free释放。
  • 不能释放已经被释放过的内存,这将导致未定义行为,可能导致程序崩溃。
  • 释放内存后,不应继续使用该内存空间,否则可能导致未定义行为和潜在的错误。
  • 在程序结束前,应确保所有动态分配的内存空间都已被释放,以避免内存泄漏

应用:

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

int main() {
    int* ptr = (int*)malloc(sizeof(int)); // 动态分配内存
    if (ptr == NULL) {
        printf("内存分配失败\n");
        return 1;
    }
    *ptr = 42; // 使用动态分配的内存
    printf("动态分配的内存中的值:%d\n", *ptr);
    free(ptr); // 释放内存
    ptr = NULL;
    return 0;
}

三、有关动态内存管理容易出现的问题

3.1 对NULL指针进行解引用操作

void test()
{
 int *p = (int *)malloc(INT_MAX/4);
 *p = 20;//如果p的值是NULL,就会有问题
 free(p);
}

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

void test()
{
 int i = 0;
 int *p = (int *)malloc(10*sizeof(int));
 if(NULL == p)
 {
 exit(EXIT_FAILURE);
 }
 for(i=0; i<=10; i++)
 {
 *(p+i) = i;//当i是10的时候越界访问
 }
 free(p);
}

3.3 对于非动态内存进行free

void test()
{
 int i = 0;
 int *p = (int *)malloc(10*sizeof(int));
 if(NULL == p)
 {
 exit(EXIT_FAILURE);
 }
 for(i=0; i<=10; i++)
 {
 *(p+i) = i;//当i是10的时候越界访问
 }
 free(p);
}

3.4  动态开辟内存忘记释放( 内存泄漏 )

void test(void)
{
	int* p = (int*)malloc(sizeof(int));
	if (p == NULL){
		perror("malloc");
	}

}

int mian()
{
	test();
	return 0;
}

 

  • 42
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
C语言可以通过指针和动态内存分配函数来模拟内存管理。下面是一个简单的例子: ```c #include <stdio.h> #include <stdlib.h> #define MEM_SIZE 1024 // 内存大小 char memory[MEM_SIZE]; // 模拟内存 void* my_malloc(size_t size) { static char* p = memory; // 内存分配指针,初始指向内存起始地址 void* ret = p; // 返回值指针 p += size; // 内存分配指针移动到下一个可用位置 if (p > memory + MEM_SIZE) { // 检查是否内存溢出 printf("Error: Out of memory.\n"); exit(EXIT_FAILURE); } return ret; } void my_free(void* ptr) { // 空函数,因为这里不需要释放内存 } int main() { int* p = (int*)my_malloc(sizeof(int)); // 分配4个字节的内存 *p = 123; // 写入数据 printf("%d\n", *p); // 读取数据 my_free(p); // 释放内存(空函数,不做任何操作) return 0; } ``` 在上面的例子中,`my_malloc`函数模拟了动态内存分配,使用一个指针`p`记录当前可用的内存位置,并返回分配的内存地址;`my_free`函数则模拟了内存释放,但实际上并不需要释放内存。在主函数中,使用`my_malloc`分配了4个字节的内存,并在指针`p`指向的内存地址处写入数据和读取数据,最后使用`my_free`释放内存(空函数,不做任何操作)。 当然,这只是一个简单的例子,实际上内存管理涉及到很多复杂的问题,如内存碎片、内存泄漏、二级分配等等,需要充分考虑各种情况,才能保证程序的正确性和性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值