AI吃大瓜 2018-05-15 04:35 采纳率: 75%
浏览 2173
已采纳

malloc动态创建一维、二维数组,内存释放的问题

 //////////////c用malloc和free//////////////////////////////
#include   "stdio.h"   
#include <iostream>
using namespace std;

//***********使用malloc创建一维数组,初始化、打印和释放***********
#define MALLOC_1D(p1,len,TYPE) p1 = (TYPE *)malloc(len * sizeof(TYPE));

#define FREE_1D(p1) free(p1);

template<typename TYPE>
void MALLOC_1D_INIT(TYPE *p1, int len, TYPE value = 0) {
    for (int i = 0; i<len; i++)
            p1[i] = value;
}


template<typename TYPE>
void PRINT_1D(TYPE *p1, int len) {
    for (int i = 0; i < len; i++) {
            cout << p1[i] << ",";
    }
    cout << endl;
}

//***********使用malloc创建二维数组,初始化、打印和释放***********
#define MALLOC_2D(p2,row,col,TYPE)\
p2 = (TYPE**)malloc(sizeof(TYPE*) *row);\
for (int i = 0; i < row; i++)\
    p2[i] = (TYPE*)malloc(sizeof(TYPE) * col);


#define FREE_2D(p2,row,col)\
    for (int i = 0; i<row; i++)\
        free(p2[i]);\
    free(p2);


template<typename TYPE>
void MALLOC_2D_INIT(TYPE **p2, int row, int col, TYPE value=0) {
    for (int i = 0; i<row; i++)
        for (int j = 0; j<col; j++)
        {
            p2[i][j] = value;
        }
}

template<typename TYPE>
void PRINT_2D(TYPE **p2, int row, int col) {
    for (int i = 0; i < row; i++) {
        for (int j = 0; j<col; j++)
        {
            cout << p2[i][j] << ",";
        }
        cout << endl;
    }
    cout << endl;
}


void   main()
{

    int row = 3;
    int col = 5;
    int cha = 4;
    //一维数组
    int *p1;
    MALLOC_1D(p1, row, int);//开辟数组空间
    MALLOC_1D_INIT(p1, row);//数组初试化
    PRINT_1D(p1, row);//打印
    FREE_1D(p1);//释放空间
    cout << " p1[0]="<<p1[0] << endl;//【1】明明free释放了,为什么还可以访问内存?

    //二维数组
    int **p2;
    MALLOC_2D(p2, row, col, int);//开辟数组空间
    MALLOC_2D_INIT(p2, row, col);//数组初试化
    PRINT_2D(p2, row, col);//打印
    FREE_2D(p2, row, col);//释放空间
    //cout << " p2[0][0]=" << p2[0][0] << endl;//【2】free释放了,不能访问了,去掉注释出错!
    system("pause");
}

我的问题是:
【1】malloc创建的一维数组,明明free释放了,为什么还可以访问内存?是我没有成功释放内存麽?而我malloc创建的二维数组,free释放了后不能访问了
【2】如何检测自己malloc动态开辟的空间,被成功free了?

  • 写回答

7条回答 默认 最新

  • ChenSu2008 2018-05-15 06:55
    关注

    对于一维“数组”
    数组的实现是在栈上申请连续的内存区间,malloc是在堆上申请一个连续的内存区间,可以用[]来操作,但是并非数组。
    (以后你会慢慢发现很多基础概念不能混淆)

    对于回收后可以访问的话,可以看下帖。简言之,只是通知系统这块内存释放了,系统根据自己的算法决定何时回收。
    http://bbs.chinaunix.net/thread-1396686-1-1.html

    当然自己通知了系统不用了,就应该保证不用这块内存了,所以释放后立即p1 = NULL是基本的变成规范。

    对于二维“数组”
    其实这个问题就出在数组的理解上,这边只是申请一个连续的区域,区域的每个值也指向另外的一篇连续的区域
    其实这里所有的区域并不一定是连续的(p2[0]和p2[1]指向的区域是堆的随机分配的),而真正的二维数组是连续的栈上的区域

    然后回答你的问题
    【1】=>p1是系统还没有来回收,p2的话,抱歉,身边没有环境,我理解是应该可能系统对于是当前域内({}中)是执行完了再回收。
    实际上应用上是没有人这么写代码的,因为指针释放后还在用的话是被批了多少年的问题了。。。
    【2】=>根本没有这样的需求,已经释放掉东西还要去检查就是要用到了,这是矛盾的。
    如果真有这样的要求(为了防止内存泄漏),我觉得你可以去看看智能指针的使用或者自己实现内存申请和释放

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
  • 白色一大坨 2018-05-15 04:49
    关注

    【1】虽然你释放了,但是还是可以引用的,内存其实已经无效,这种指针被称为“野指针”;
    比如你看一下p2[0]其实也是可以用的
    【2】一般使用指针时会初始化为null,而释放之后会再次赋值为null,这样就可以通过指针是否为null来判断当前指针是否被占用。

    评论
  • _1_1_7_ 2018-05-15 07:25
    关注

    malloc ,用完 free ,按规范写代码就可以了,不用纠结

    评论
  • liuhulh001 2018-05-15 07:53
    关注

    free释放之后,最保险的做法是要 赋值NULL,防止去访问,造成越界

    评论
  • Leo-hrbeu 2018-05-15 10:39
    关注

    【1】malloc创建的一维数组,明明free释放了,为什么还可以访问内存?是我没有成功释放内存麽?而我malloc创建的二维数组,free释放了后不能访问了
    A:你使用free释放内存只是告诉系统这块内存区域可以被重新分配使用了,内存本身还在,如果没有被重新分配使用,原来的内容也在!还可以用原来的指针或数组继续访问,单访结果可能是原来的内容,也可能被其他程序修改了!

    【2】如何检测自己malloc动态开辟的空间,被成功free了?
    一般来说没有什么检测malloc动态开辟的空间被成功free的方法,通常的做法free一个内存空间后要及时将使用该内存空间的指针赋值为NULL,避免成为“野指针”!

    评论
  • h1217880811 2018-05-15 15:02
    关注

    看到p2[0][0]了吧,在汇编代码中,是先访问一级指针,然后再访问一级指针指向的值。
    简单点说,当你free后,一级指针指向的值都变了,你还能用一级指针访问二级指针嘛?所以出错。
    因为你p1,p2释放后没有赋值为null,所以p1[0],p2[0]都是能访问的。
    但你free后,内存值都会变动。p1[0]的值绝不会是原先的值了,一般你打印出来为负数。
    所以p2[0][0]去访问时,p2[0]的值变为负数了,还能找到p2[0]【0]嘛?
    也就是p2[0]指向的地址是不可访问的,至于为何不可访问,这是 cpu保护模式 里面的知识,这是虚拟内存的相关概念。
    你完全可以在编程工具中打汇编窗口和内存窗口打开去调试。一目了然!!
    解释的够清楚了嘛?

    评论
  • juertql 2018-05-16 06:49
    关注

    free()释放的是指针指向的内存。释放了内存空间后,原来指向这块空间的指针还是存在!
    free()的作用就是标记这块内存可以再次被分配。
    访问free后的指针的行为是不确定的,有可能被其他程序再次分配了,有可能什么都没变。

    看看free的实现:
    void free(void *ptr)
    {
    struct mem_control_block *free;
    free = ptr - sizeof(struct mem_control_block);
    free->is_available = 1;
    return;
    }

    实际上没对指针和内存的内容做操作,只是设置了一个可用的标志位。所以释放内存后正确的做法是把指针指向NULL。

    评论
查看更多回答(6条)

报告相同问题?

悬赏问题

  • ¥15 寻涂色内存脚本作者有项目有市场有资源.却技术
  • ¥15 蓝桥杯c51单片机问题
  • ¥15 ajax跨域问题请求修改代码
  • ¥15 python matplotlib
  • ¥15 短信测压+语音,有偿,必须用Python
  • ¥20 COCOS2DX的protobuf协议注册函数问题
  • ¥15 (标签-Pytorch|关键词-Stream)
  • ¥15 求深圳2019年开放数据应用创新大赛的营运车辆数据!
  • ¥15 软件UI界面绘制折线图
  • ¥20 用c语言写一个团队考勤系统