#2Hz
2021-07-08 21:43
采纳率: 100%
浏览 48

C++内存管理 怎么避免内存重复释放?

#include <cstdio>
class Example{
    public:
        int *n;
        Example(int *n):n(n){}
        ~Example(){
            delete n;  // if(n != NULL)并不管用, 有啥其他检查方法吗? 
            n = NULL;
            printf("已释放内存\n");
        }
};

int main(){
    int *x = new int(666);
    Example *a = new Example(x);  //... 
    Example *b = new Example(x);  //两个类中的指针指向同一块内存 
    printf("a->n: %p, b->n: %p, x: %d\n", a->n, b->n, *x);
    delete a;
    printf("a->n: %p, b->n: %p, x: %d\n", a->n, b->n, *x);
    delete b;  //对 x 指向的内存进行了二次释放! 
    return 0;
}

运行结果:↓

a->n: 00B12E20, b->n: 00B12E20, x: 666
已释放内存
a->n: 00B12E20, b->n: 00B12E20, x: 11611744
已释放内存

两个实例的成员变量指向了同一块内存,当我要销毁这两个实例时,同一块的内存被释放了两次。
重复释放内存是个很危险的操作,那我现在该怎么解决这个问题?

我的理想办法是在析构函数那加一条“内存是否为空”的判断,但就一直找不到实现方法。。
还是说这就是C++内存管理的难点,只能通过合理的设计结构来避免?

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • bostonAlen 2021-07-08 23:58
    已采纳

    你这里为空判断无法生效,是因为delete后,n变成0xDDDDDDDD , 自然NULL无法判断

    #include <cstdio>
    class Example{
        public:
            int *n;
            Example(int *n):n(n){}
            ~Example(){
                if(n != (int *)0xDDDDDDDD)
                {
                delete n;  // if(n != NULL)并不管用, 有啥其他检查方法吗? 
                n = NULL;
                printf("已释放内存\n");
                }
                
            }
    };
    int main(){
        int *x = new int(666);
        Example *a = new Example(x);  //... 
        Example *b = new Example(x);  //两个类中的指针指向同一块内存 
        printf("a->n: %p, b->n: %p, x: %d\n", a->n, b->n, *x);
        delete a;
        printf("a->n: %p, b->n: %p, x: %d\n", a->n, b->n, *x);
        delete b;  //对 x 指向的内存进行了二次释放! 
        return 0;
    }
    
    

    但是这样还是有问题,第二次析构,又无法判断了,还是会对损坏。
    最好的还是,不进行地址的指向,仅仅是数据的赋值。

    #include <cstdio>
    
    class Example{
        public:
            int *n;
            Example(int *n):n(new int()){*n = *n;}
            ~Example(){
                if(n != (int *)0xDDDDDDDD || n!=NULL)
                {
                delete n;  // if(n != NULL)并不管用, 有啥其他检查方法吗? 
                n = NULL;
                printf("已释放内存\n");
                }
            }
    };
    int main(){
        int *x = new int(666);
        Example *a = new Example(x);  //... 
        Example *b = new Example(x);  //两个类中的指针指向同一块内存 
        printf("a->n: %p, b->n: %p, x: %d\n", a->n, b->n, *x);
        delete a;
        printf("a->n: %p, b->n: %p, x: %d\n", a->n, b->n, *x);
        delete b;  //对 x 指向的内存进行了二次释放! 
        printf("a->n: %p, b->n: %p, x: %d\n", a->n, b->n, *x);
        return 0;
    }
    
    
    已采纳该答案
    1 打赏 评论
  • 祝哥靓 2021-07-09 06:58

    这样的编程方式很不好,好的方式是“谁申请,谁释放”,Example类不应该进行释放操作
    如果你一定要这样做,可以传入x的地址,但也要考虑x的作用域,

    #include <cstdio>
    class Example{
        public:
            int ** n;
            Example(int ** n):n(n){}
            ~Example(){
                if(*n != NULL)
                {
                    delete *n;  
                    *n = NULL;
                    printf("已释放内存\n");
                } 
            }
    };
    int main(){
        int *x = new int(666);
        Example *a = new Example(&x);  //... 
        Example *b = new Example(&x);  //两个类中的指针指向同一块内存 
        printf("a->n: %p, b->n: %p, x: %d\n", a->n, b->n, *x);
        delete a;
        printf("a->n: %p, b->n: %p, x: %d\n", a->n, b->n, *x);
        delete b;  
        return 0;
    }
    
    
    1 打赏 评论

相关推荐 更多相似问题