C 语言内存管理

一、内存管理" title="内存管理">内存管理

  1. malloc:申请动态内存空间
  2. free:释放动态内存空间
  3. calloc:申请并初始化一系列内存空间
  4. realloc:重新分配内存空间

注意这些函数都是在头文件中

1.malloc:申请动态内存空间 存放在堆中

函数原型:void *malloc(size_t size);

malloc 函数向系统申请分配size个字节的空间,并返回一个指向这块空间的指针。

如果函数调用成功,返回一个指向申请的内存空间的指针,由于返回类型是void指针(void *),所有它可以被转换成任何类型的数据;如果函数调用失败,返回值是NULL。另外,如果size参数设置为0,返回值也可能是NULL,但这并不意味着函数调用失败。

2.free:释放动态内存空间

动态内存是存放在堆中的,如果你不主动去释放堆上的内存资源,那么他将永远的存在,直到程序关闭。

函数原型:void free(void *ptr);

free函数将释放ptr参数指向的内存空间。该内存空间必须是由 malloc、calloc、realloc 函数申请的。否则该函数将导致未定义行为。如果ptr参数是NULL,则不执行任何操作。注意:该函数并不会修改ptr参数的值,所以调用后任然指向原来的地方(变为非法空间)。

#include<stdio.h>

#include<stdlib.h>

int main(){

int *ptr;

ptr = (int *)malloc(sizeof(int));

if(ptr == NULL){//一般内存不够用的时候会失败

printf("分配内存失败!\n");

exit(1);

}

printf("请输入一个整数:");

scanf("%d",ptr);

printf("你输入的整数是:%d\n",*ptr);//520

free(ptr);//释放

printf("你输入的整数是:%d\n",*ptr);//0

return 0;

}

3.内存泄露

导致内存泄露主要有两种情况:

  • 一、隐式内存泄露(即用完内存块没有及时free函数释放)
  • 二、丢失内存块地址

为防止内存泄露,我们要在使用完这块内存空间之后,立刻调用free函数释放(高级语言有垃圾回收机制,而C语言则没有)

int main(void){

while(1){

malloc(1024);//循环申请内存空间,并且没有及时释放,会导致内存爆掉

}

return 0;

}

4.calloc:申请并初始化一系列内存空间

函数原型:void *calloc(size_t nmemb,size_t size);

calloc函数在内存中动态申请nmemb个长度为size的连续内存空间(即申请的总空间尺寸为nmemb*size),这些内存空间全部被初始化为0

calloc函数在申请完内存后,自动初始化该内存空间为零

5.realloc:重新分配内存空间

函数原型:realloc(void ptr,size_t size);

6.初始化内存空间

/**

以mem开头的函数被编入字符串标准库,函数的声明包含在string.h这个头文件中。

--memset-- 使用一个常量字节填充内存空间

--memcpy-- 拷贝内存空间

--memmove--

--memcpm-- 比较内存空间

--memchr-- 在内存空间汇总搜索一个字符

*/

二、内存布局

#include<stdio.h>

#include<stdlib.h>

int global_uninit_var;

int global_init_var1 = 520;

int global_init_var2 = 880;

void func(void);

void func(void){

;

}

int mian(void){

int local_var1;

int local_var2;

static int static_uninit_var;

static int static_init_var = 456;

char *str1 = "I love FishC.com!";

char *str2 = "You are right!";

int *malloc_var = (int *)malloc(sizeof(int));

printf("addr of func -> %p\n",func);

printf("addr of str1 -> %p\n",str1);

printf("addr of str2 -> %p\n",str2);

printf("addr of global_uninit_var -> %p\n",global_uninit_var);

printf("addr of global_init_var1 -> %p\n",global_init_var1);

printf("addr of global_init_var2 -> %p\n",global_init_var2);

printf("addr of static_init_var -> %p\n",static_init_var);

printf("addr of static_uninit_var -> %p\n",static_uninit_var);

printf("addr of local_var1 -> %p\n",&local_var1);

printf("addr of local_var2 -> %p\n",&local_var2);

}

C 语言内存管理

C 语言内存管理

代码段(Text segment) 通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读。在代码段中,也有可能包含一些只读的常量。

数据段(Initialized data segment) 通常用来存放已经初始化的全局变量和局部静态变量。

BSS段(Bss segment/Uninitialized data segment) 通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称,这个区段中的数据在程序运行前将被自动初始化为数字0。

堆:是用来存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩展或缩小。当进程调用malloc等函数分配内存是,新分配的内存就被动态添加到堆上;当利用free等函数释放内存时,被释放的内存从堆中被剔除。

栈:大家平时可能经常听到堆栈这个词,一般指得就是这个栈。栈是函数执行的内存区域,通常和堆共享一片区域。

堆和栈的区别

一、申请方式:

–堆是由程序员手动申请

–栈是由系统自动分配

二、释放方式:

–堆是由程序员手动释放

–栈由系统自动释放

三、生存周期:

–堆的生存周期由动态申请到程序员主动释放为止,不同函数之间均可自由访问

–栈的生存周期由函数调用开始到函数返回时结束,函数之间的局部变量不能相互访问

四、发展方向:

–堆和其他区段一样,都是从低地址向高地址发展

–栈则相反,是由高地址向低地址发展

以上是 C 语言内存管理 的全部内容, 来源链接: utcz.com/p/233586.html

回到顶部