c++ 内存越界 char*_聊一聊内存管理

关注“杜明c”,每天进步一点点

摘要
  • 内存结构

  • C语言和内存相关的四个函数

    • malloc

    • free

    • calloc

    • realloc

  • 常见的错误

    • 空指针不能访问声明

    • 了指针不等于申请了空间

    • 释放指针之后,仍然使用它

    • 内存分配之后,以为其自动初始化

    • 内存越界

    • 内存泄漏

6ee2e1f98b35a896843b32d012bacb4a.png

内存结构

一个C/C++程序在内存中占用的空间分下面几个部分

  • 代码段

  • 静态区

    • BBS段

    • 数据段

静态区

静态区分为读写段,只读段,储存全局变量,静态变量和字符串常量等等,由编译器管理,在程序结束后自动释放资源。

int i = 0;char *str = "hello world";static char c;

代码段

用于存放函数体的代码,是只读字段,在程序运行期间不会改变。

void print(int b){    int a = b;    //A    printf("%d",a);}//A,代码段将会储存 a = b;而初始化int a由编译器完成,并不储存在代码段

栈区由编译器自动管理,不需要开发者操心,由于栈后进先出的特点,适合保存\恢复现场。作为储存函数局部变量的区域,超出作用域的变量将从栈中弹出。

void fun(){    int a;  //栈区储存局部变量,在函数结束时释放。    int b;}//注意,栈区大小是有限的,不宜储存很大的数据,否则将会提示异常栈溢出。

堆区储存由malloc函数或者new操作符分配的空间,生命周期由free和delete决定,堆区可以申请很大的储存空间,在32位平台上,理论上最大可以申请4G的空间,一些很大的数据结构,动态数组,放到堆区更合适,但是一定要注意使用过后释放资源。

void fun(){    char *str = (char*)malloc(10);//申请的空间存放在堆区}
C语言和内存相关的四个函数

使用这些函数需要声明头文件 stdlib.h

内存问题在不同环境下,效果可能不一致,本文的编译环境win10,VC6。

  1. malloc

  2. free

  3. calloc

  4. realloc

malloc

void *malloc(size_t size);//声明//size:申请的字节数

C语言里,malloc函数用于申请可用的空间,但是不保证一定申请成功,失败返回NULL。

int *p = (int *)malloc(sizeof(int)*10);  //申请能容纳10位int元素的地址char *str = (char*)malloc(10);  //申请能容纳10个字符的地址if(!p)    //malloc不保证一定能申请到空间{    printf("申请空间失败!\n");}//注意:malloc返回的是无类型的地址,需要强制转换类型

可以用malloc申请一个0字节的内存吗?

char *p = (char*)malloc(0);//可以返回一个非零地址,但是不能在该地址读写,因为他可能会被之后申请的变量覆盖//并且释放该指针会导致出错

free

void free(void *ptr);//声明//ptr 需要释放的指针

free函数用于释放空间,只能释放由malloc申请的空间,否则将出现未知的错误。一个对象使用完毕之后,应该尽快释放,避免内存泄漏(其实说白了就是该内存空间使用完毕之后未回收 )。

void fun(char *p){...}char *str = (char*)malloc(10);  //申请能容纳10个字符的地址void fun(str);    //调用free(str);    //使用完毕后,释放内存str = NULL;    //同时将指针清空,避免再次使用已释放的内存

calloc

void *calloc(size_t nitems, size_t size);//calloc函数的声明/*nitems:要被分配的元素个数size  :元素的大小*/

calloc函数用于申请空间,和malloc类似,不同之处在于calloc会设置分配的内存为零。

int* a = (int*)calloc(10, sizeof(int));free(a);

realloc

//声明void *realloc(void *ptr, size_t size);/*ptr :指向一个由malloc或者calloc申请的内存地址size:内存块的新大小,字节为单位*/

用realloc尝试重新调整之前调用 malloccalloc 所分配的 ptr 所指向的内存块的大小。(简而言之,内存不够用,申请更大的空间)

char *str = (char *) malloc(15);strcpy(str, "杜明c");              //字符串复制函数printf("字符串地址:%p\n",str);str = (char *) realloc(str, 25);  //重新分配空间strcat(str, "语言");              //追加字符串printf("重新分配空间后:%p\n",str);printf("str:%s\n",str);    free(str);----out----字符串地址   :00883940重新分配空间后:00883940str:杜明c语言

在C++中,new,delete和 malloc,free有类似的作用

int *num = new int(5);     //将整数赋值为5int *nums = new int[100];  //申请一个大小为100的整型数组空间int **nums = new int[5][6];  //二维数组delete num;    //删除整数delete[] nums;  //删除数组
常见的内存错误

初学者经常犯的一些错误。

  1. 空指针不能访问

//使用指针之前,附加一个判断void fun1(char *p){    if(p==NULL)    return;    ...}
  1. 声明了指针不等于申请了空间

struct student{    char name[10];    int age;};struct student *p;p->age = 17;    //错误p = (struct student *)malloc(sizeof(struct student));//正确p->age = 17;
  1. 释放指针之后,仍然使用它

char *p = (char *)malloc(10);free(p);strcpy(p, "杜明c");    //错误
  1. 内存分配之后,以为其自动初始化

int i;while(i<10)  //实际上,可能不仅仅只执行10次,i未初始化,可能为任何值{    ...    i++;}
  1. 内存越界

int nums[10];int i = 0;for(;i<=10;i++){    printf("%d\n",nums[i]);  //内存越界,没有nums[10]}
  1. 内存泄漏

就是该内存空间使用完毕之后未回收。

int i = 0;char *p;for(;i<=10;i++){    p = (char *)malloc(10);    //申请了内存,却没有完全释放}free(p);  //只释放了一次

End

    杜明C语言

  专注C/C++

每天进步一点点

长按关注 b40286e79d6ea5423f0a3fe9d7f84435.png

写留言

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值