目录
总结. 对动态内存切不可越界访问或赋值,如果当前的指针的容量不够了,可以使用realloc()函数扩容
前言
通过malloc申请一块内存当数组用时,如果越界访问或赋值会产生什么后果呢?可能产生两种后果:
1. 访问(或赋值)的可能是 其他指针变量中地址,造成程序逻辑错误。
2. 访问(或赋值)的地址为非法地址,直接造成程序崩溃。
一. 越界 可以赋值成功,但千万不要这样干
下面定义两个 指针变量ptr1和ptr2变量,申请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中的地址为 0x5555555592a0,ptr2中的地址为 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编译时通过的,所以务必要仔细对待。