C语言 动态分配内存

@Chita_

C语言 动态分配内存

  • 动态内存管理
  • callco
  • free
  • malloc
  • realloc
  • 动态内存的常见问题

重述:指针的用法

1)提供访问存储在数组中的信息的另一种方法
2)提供另一种(更有效的)向函数传递参数的方法
3)启用动态数据结构,这些数据结构是在运行时从堆中分配的内存块构建的

为什么要动态分配内存?

  • 可能不能提前知道存储数据所需的变量(如数组)空间
  • 与静态分配相比:
    - 如果预定义的大小很小,它可能没有足够的空间来容纳数据,从而导致程序失败
    - 如果预先设定的大小较大,大部分空间将不会被利用,造成浪费或效率低下

动态分配内存

  • 允许程序在执行过程中动态地为一些变量(如数组)分配内存
  • 方法:
    - 程序有允许用户请求一定量内存的例程
    - 然后用户使用这个内存,并在它们完成时返回它
    - 在堆段中分配内存

动态内存管理的函数

  • calloc - - - 分配内存数组
  • malloc - - - 分配单个内存块
  • realloc - - - 扩展或减少先前分配的空间量
  • free - - - 释放一块不再需要的内存

动态分配的内存不会在函数结束时消失,必须显式地释放它

calloc - 分配内存数组

void *calloc(size_t num, size_t esize);
  • size_t : 用于指示大小的特殊类型, unsigned int
  • num : 要在数组中分配的元素数
  • esize: 要分配单个元素的大小(以字节为单位)
    - 以获得正确的值,使用sizeof(< type >)
    - 分配的内存大小为num*esize
  • calloc返回该内存的第一个字节的地址
    - 将返回的地址转换为适当的类型
  • 如果没有足够的可用内存,calloc返回NULL
float *nums;
int a_size;
int idx;
printf("Read how many numbers:");
scanf("%d",&a_size);
nums = (float *)calloc(a_size, sizeof(float));
/* nums is now an array of floats of size a_size */
for (idx = 0; idx < a_size; idx++) {
printf("Please enter number %d: ",idx+1);
scanf("%f", nums+idx); /* read in the floats */
}
/* Calculate average, etc. */

潜在的问题在哪里?
- nums+idx是地址, 后续输出时应输出nums[idx]

始终检查calloc,malloc或realloc的返回值!

float *nums;
int a_size;
int idx;
printf("Read how many numbers:");
scanf("%d",&a_size);
nums = (float *) calloc(a_size, sizeof(float));
if(nums == NULL) {
/* exit or do some other stuff */
}

free - 将内存返回堆

void free(void *ptr);
  • 由ptr指向的位置的内存被释放(以便可以再次使用)
  • 程序跟踪由内存开始位置分配的每个内存
  • 如果释放一块分配有calloc的内存,则将释放(释放)整个数组
  • 未定义行为,如果我们作为地址传递以释放未动态分配(或已经释放)的地址
float *nums;
int a_size;
printf("Read how many numbers:");
scanf("%d",&a_size);
nums = (float *) calloc(a_size, sizeof(float));
/* Use array nums *//* When done with nums: */
free(nums);
/* Would be an error to do it again - free(nums) */

malloc - 分配内存

void *malloc(size_t esize);
  • 类似于calloc,不同的是我们使用它来分配给定大小的单个块
  • 如果内存不足,返回NULL
  • 如果不再需要内存,则必须使用free释放内存
  • 以下是等价的:
  • malloc(a_size*sizeof(float)); <==>calloc(a_size, sizeof(float));
float *nums;
int a_size;
int idx;
printf("Read how many numbers:");
scanf("%d",&a_size);
nums = (float *) malloc(a_size * sizeof(float));
if(nums == NULL) {
/* exit or do some other stuff */
}

realloc - 增加/减少内存分配

void *realloc(void *ptr, size_t esize);
  • ptr是一个指向先前动态分配的一块内存的指针
  • size是要分配的新大小
  • 如果重新分配失败,返回NULL
  • 函数执行以下操作:
    1) 分配size大小的内存
    2) 将ptr内存中的内容复制到新内存的第一部分
    3) —释放旧的内存块
    4) 返回到新内存块的地址
float *nums;
int a_size;
nums = (float *)calloc(5, sizeof(float));
/* nums is an array of 5 floating point values */
for (a_size = 0; a_size < 5; a_size++)
	nums[a_size] = 2.0 * a_size;
/* nums[0]=0.0, nums[1]=2.0, nums[2]=4.0, etc. */
nums = (float *)realloc(nums, 10*sizeof(float));
/* An array of 10 floating point values is allocated, the
first 5 floats from the old nums are copied as the first 5
floats of the new nums, then the old nums is released */

分配二维数组的内存

  • 不能简单地动态分配二维及多维数组
  • 解决
    1)分配一个指针数组(一维)
    2)使每个指针指向一个大小合适的一维数组
float **A; /* A is an array (pointer) of float pointers */
int X;
A = (float **) calloc(5, sizeof(float *));
/* A is a 1D array (size 5) of float pointers */
for (X = 0; X < 5; X++)
	A[X] = (float *) calloc(4, sizeof(float));
/* Each element of array points to an array of 4 float
variables */
/* A[X][Y] is the Yth entry in the array that the Xth member of A
points to */

不规则尺寸的2D阵列
在这里插入图片描述

float **A;
int X;
A = (float **)calloc(5, sizeof(float *));
for (X = 0; X < 5; X++)
	A[X] = (float *) calloc(X+1, sizeof(float));

动态内存的常见问题

问题1
返回一个指向自动变量的指针

int foo(void)
{
int x;

return &x;
/
x does not exist outside the function /
/
Returning its address will result in unknown behaviour */
}

问题2
堆块溢出:类似于数组越界

void foo(void)
{
int *x = (int ) malloc(10 * sizeof(int));
x[10] = 10;
/
Allocated memory is only up to x[9] */

free(x);
}

问题3
内存泄漏:丢失指向已分配内存的指针

int pi;
void foo(void)
{
pi = (int
) malloc(8sizeof(int));
/
Leaked the old memory pointed to by pi /

free(pi); /
foo() is done with pi, so free it /
}
int main(void)
{
pi = (int
) malloc(4*sizeof(int));
foo();
}

问题4

  • 潜在的内存泄漏
    - 内存块开始的指针丢失
    - 仍然可以通过指针算术恢复

int *ip = NULL;
void foo(void)
{
ip = (int ) malloc(2 * sizeof(int));

ip++;
/
ip is not pointing to the start of the block anymore */
}

问题5
释放非堆或未分配的内存

void foo(void)
{
int fnh = 0;
free(&fnh); /* Freeing stack memory */
}
void bar(void)
{
int *fum = (int ) malloc(4 * sizeof(int));
free(fum+1); /
fum+1 points to middle of block /
free(fum);
free(fum); /
Freeing already freed memory */
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在语言中,使用malloc函数可以动态地分配内存空间。引用中的示例代码演示了如何使用malloc函数分配一个包含10个整数的数组,并将其初始化为0。首先,需要在代码中包含<stdio.h>和<stdlib.h>头文件。然后,使用int类型的指针变量arr来指向分配的内存空间。通过调用malloc函数,并传递n * sizeof(int)作为参数,可以分配n个整数大小的内存空间。若分配失败,则打印错误信息并返回-1。接下来,使用for循环将数组中的元素初始化为0。最后,使用free函数释放动态分配的内存空间。引用中给出了realloc函数的使用格式,用于在已分配的内存空间上进行扩容。引用中的示例代码展示了如何使用malloc函数分配一个字符串的内存空间,并在使用完后使用free函数释放内存。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [【c语言】(动态内存分配)malloc函数解析](https://blog.csdn.net/m0_72301367/article/details/130394594)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [C语言动态内存分配(malloc(),free(),calloc(),realloc())](https://blog.csdn.net/weixin_50803498/article/details/126147934)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [C语言动态内存分配:(一)malloc/free的实现及malloc实际分配/释放的内存](https://blog.csdn.net/u012846795/article/details/117808593)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值