【C语言】malloc()管理的动态内存越界访问的危害

目录

前言

一.  越界 可以赋值成功,但千万不要这样干

二 . 越界 可能修改其他指针指向地址内的值

三. 越界 可能直接导致程序崩溃

总结.  对动态内存切不可越界访问或赋值,如果当前的指针的容量不够了,可以使用realloc()函数扩容


前言

通过malloc申请一块内存当数组用时,如果越界访问或赋值会产生什么后果呢?可能产生两种后果:

1. 访问(或赋值)的可能是 其他指针变量中地址,造成程序逻辑错误。

2. 访问(或赋值)的地址为非法地址,直接造成程序崩溃。

一.  越界 可以赋值成功,但千万不要这样干

下面定义两个 指针变量ptr1ptr2变量,申请3个整型的内存, 地址赋值给ptr1;申请1个整型长度内存,起始地址赋值诶ptr2

#include <stdio.h>
#include <stdlib.h>
int main(){

  int * ptr1,* ptr2;/*定义两个整型指针*/
  int i=0;
  ptr1= (int * ) malloc(sizeof(int)*3);/*给ptr1分配三个整型长度的内存,虽然是申请3个整型长度,                  
                                         在64位linux中真实的分配空间为8个整型*/
   ptr2=(int *) malloc(sizeof(int));

  *ptr2=3002;  /*先给ptr2指向地址赋值3002*/
  printf("ptr2地址中的值为:%d\n",*ptr2);

  printf("ptr1数组的值:");
  for(i=0;i<9;i++){
          ptr1[i]=i+1;               /*当给ptr[8]赋值时,会改变ptr2地址中的值*/
        printf("%d\t",ptr1[i]);
  }
  printf("p2地址中的值为:%d\n",*ptr2);
  ptr1=(int *) realloc(ptr1,sizeof(int)*6); /*这里会调用失败,因为给给ptr[2]以后的地址赋值了
                                            ,内存越界了,造成realloc无法获取准确的内存位置*/
  free(ptr1);
  free(ptr2);
  return 0;

}

      调试可见ptr1中的地址为 0x5555555592a0ptr2中的地址为 0x5555555592c0

(gdb) p ptr1              /*打印ptr1保存的地址*/
$2 = (int *) 0x5555555592a0
(gdb) p ptr2              /*打印ptr2保存的地址*/
$3 = (int *) 0x5555555592c0
(gdb) p ptr2-ptr1         /*ptr2比ptr1多8个整型的长度*/
$4 = 8

        ptr1虽然只申请了三个整型的长度的内存,但实际程序分配的长度为8个整型长度(即使申请的是3个整型长度,但malloc有一个内存对齐的要求,所以会返回给ptr1 8个整型长度),即ptr2-ptr1=8。所以给ptr[0]到ptr[7]一个8个地址赋值都没问题,但千万千万不要这样做,即使是给ptr[0]到ptr[7]赋值成功,,后面调用realloc()也无法正确的扩容,会报错。况且还会造成下面两种可能严重的后果。

二 . 越界 可能修改其他指针指向地址内的值

在执行完   *ptr2=3002 ;  之后,内存如下

给ptr1赋值

 for(i=0;i<9;i++){
     ptr1[i]=i+1;
     printf("%d\t",ptr1[i]);
 }

会把ptr2值修改掉, 内存如下

三. 越界 可能直接导致程序崩溃

malloc() 和free() 两个函数其实是管理一个内存池(链表结构实现的),当它们管理的内存不够时,会向操作系统请求更大内存放入到内存池中。如果越界访问,很有可能访问的是malloc()管理的内存池之外的地址,那样程序就崩溃了。

总结.  对动态内存切不可越界访问或赋值,如果当前的指针的容量不够了,可以使用realloc()函数扩容

一般在windows下,vs会自动识别这个越界的错误,但是在linux下的gcc编译时通过的,所以务必要仔细对待。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值