乐趣区

关于c:动态内存管理

动静开拓内存

malloc 开拓内存

#include <stdlib.h>
void *malloc(size_t size)
  • size:须要开拓的内存空间的大小,以字节为单位。
  • 返回值:返回一个指向开拓的内存空间的指针(void* 类型,须要其余类型时应用强制类型转换即可)
  • 如果申请失败,则返回 NULL。

free 开释空间

void free(void *ptr)
  • 函数作用:开释之前调用 calloc、malloc 或 realloc 所调配的内存空间。
  • ptr:指针指向一个要开释内存的内存块。
  • 个别在开释空间时,同时也会将该空间的指针赋值为 NULL,防止它成为野指针。
  • 如果不开释申请的内存空间,在程序完结时,会由操作系统主动回收。

calloc 开拓内存

  • malloc 和 calloc 之间的不同点是:calloc 会将申请的空间初始化为 0,而 malloc 是随机值。
  • void *calloc(size_t nitems, size_t size)
  • nitems:要被调配的元素个数。
  • size:元素的大小。
  • 如果申请失败,则返回 NULL。

realloc 从新分配内存

void *realloc(void *ptr, size_t size)
  • ptr:须要从新分配内存的内存块的指针。

    • 该内存块之前是通过调用 malloc、calloc 或 realloc 进行分配内存的。
    • 如果为空指针,则会调配一个新的内存块。
  • size:内存块的新的大小,以字节为单位。

    • 如果大小为 0,且 ptr 指向一个已存在的内存块,则 ptr 所指向的内存块会被开释,并返回一个空指针。
  • 留神:

    • 如果源内存前面的空间足够大,则 realloc 会在源空间前面追加分配内存。
    • 如果源内存前面的空间不够大,则 realloc 会在其余空间分配内存,并且将原来空间的值顺次拷贝过来,而后将原来的空间开释掉。

常见的动态内存谬误

对 NULL 指针的解援用操作

int main()
{int* p = (int*)malloc(1000);
    *p = 10;  // 如果内存调配失败,malloc 返回 NULL,这里就会出错
    return 0;
}
  • 解决办法:进行 NULL 检测(判断 malloc(1000) 是否等于 NULL)

对动静开拓空间的越界拜访

int* p = (int*)malloc(1000);
for (int i = 0;i<1000;i++)
{*(p + i) = i;  // 这里当 i 超过 250 后,就会呈现越界拜访
}

对非动静开拓内存的开释

int a = 10;
int* p = &a;
free(p);     // a 是局部变量,不能用 free 开释,由零碎主动开释
p = NULL;

对动静开拓的空间只开释一部分

int* p = (int*)malloc(100);
for (int i = 0; i < 50; i++)
{p++;}
free(p);    // 此时指针 p 曾经指向开拓的空间两头局部了,只能开释指针之后的局部
p = NULL;

对同一块内存屡次开释

int* p = (int*)malloc(100);
free(p);    
p = NULL;
free(p);    // 屡次开释,程序会出错。p = NULL;
退出移动版