C ++如何解决我的内存泄漏

c++ how to solve my memory leak?

本文关键字:我的 内存 泄漏 解决 何解决      更新时间:2023-10-16

考虑整数的二进制类表示的以下含义:

class Binary {
private:
    int *digits;
    int first1;
public:
    Binary() {
        digits = new int[128];
        digits[0]=0;
        first1=0;
    }
    ~Binary() {
        cout<<"deleting"<<endl;
        delete [] digits;
    }
    Binary(const Binary& b){
        digits = new int[128];
        memcpy(digits,b.digits,128*sizeof(int));
        first1=b.first1;
    }
    explicit Binary(double x){
        int n=(int)x,i;
        digits = new int[128];
        for (i=0; n ; i++,n>>=1) digits[i]=(n & 1)? 1:0;
        first1=i-1;
    }
    Binary& operator =(const Binary& b){
        if (this==&b) return *this;
        memcpy(digits,b.digits,128*sizeof(int));
        first1=b.first1;
        return *this;
    }
    Binary(int n) {
        int i;
        digits = new int[128];
        for (i=0; n ; i++,n>>=1) digits[i]=(n & 1)? 1:0;
        first1=i-1;
    }
    void print() {
        for (int i=first1; i>=0 ; i--) cout<<digits[i];
        cout<<endl;
    }
    operator int() {
        int x = 1,sum=0;
        for (int i=0; i<=first1 ; i++,x<<=1) sum+=digits[i]*x;
        return sum;
    }
    Binary& operator +(Binary& a) {
        int overflow = 0;
        Binary* b1=new Binary();
        int max = a.first1>this->first1? a.first1 : this->first1,bit;
        for (int i=0; i<=max ; i++) {
            bit=a.digits[i]+this->digits[i]+overflow;
            overflow=0;
            if (bit>1) overflow=1;
            b1->digits[i]=bit%2;
        }
        return *b1;
    }
};

以及使用它的主要内容:

int main() {
    Binary b(91);
    int x=9;
    Binary *b2=new Binary();
    *b2=b+x;
    x=*b2;
    b2->print();
    cout<<" = "<<x;
    cin>>x;
}

让我们谈谈这条线:

*b2=b+x;

首先,编译器为 int x 隐式分配一个新的二进制实例,然后将其用作加法的参数,然后为加法结果创建一个新的二进制实例,并将其逐位复制到 *B2。

问题是,如果您运行此代码,它只会打印删除一次,而为执行命令创建了 2 个对象。 显然,加法代码存在泄漏,其中我显式创建了一个新对象来返回结果。

Q1:我说的对吗?

Q2:我能做些什么来克服这个问题?

编辑:有关运算符重载主题的答案和更多信息可以在这里找到

摘要:分配了new的对象必须使用 delete 删除。 使用 new[] 分配的对象必须使用 delete[] 删除。 全局变量和局部变量在其作用域/TU 执行结束时会自动删除。 在Binary& operator +(Binary& a)中,你做了一个泄漏的Binary,在main你做了另一个泄露的Binary

如果这样写operator+,这些问题就可以避免:

Binary operator +(Binary& a) const{ //return by value
    Binary b1(*this); //hold it on the stack
    //math here
    return b1; //return by value
}

如果主要情况下您也避免了分配:

Binary b2 = b+x;
x = b2;
b2.print();

这将比您的原始代码更快,更容易阅读和理解,并且不会泄漏。

[其他注意事项]

对内部数据使用std::vector,而不是管理自己的动态数组。 vector更容易,也不太可能犯错误。

通常,最好尽可能明确地进行转化(例如int -> Binary)。 它增加了打字,但省去了麻烦。 这也适用于您的int转换运算符。

使常量

函数常量。 现在,如果你得到一个const Binary,你几乎不能用它做任何事情。 你不能打印它,你不能添加任何东西...

您似乎每int存储一位,这意味着您使用的空间比需要的多 97%(浪费了 99.999999995% 的值),这太愚蠢了。 大多数新手从每char 0-9开始,这只浪费了50%的空间。(虽然这仍然是 96% 的值),但真的很容易理解。

正常的加法方法是这样的:

Binary& operator+=(const Binary& rhs) { 
    int max = a.first1>this->first1? a.first1 : this->first1,bit;
    for (int i=0; i<=max ; i++) {
        bit=a.digits[i]+this->digits[i]+overflow;
        overflow=0;
        if (bit>1) overflow=1;
        b1->digits[i]=bit%2;
    }
}  
Binary friend operator+(Binary lhs, const Binary& rhs) {  
{return lhs+=rhs;}

如果你真的只看到"删除"一次,那么这一定是变量b。 *b2 = b+x可以通过将 b 转换为 int,添加 x,从中构造一个二进制并将其复制到 b2 指向的位置来完成。由于 b2 只是一个原始指针,因此您正在泄漏初始 *b2 实例和覆盖它的实例。

你不会在 main 的末尾删除 b2。

此外,运算符应按值返回,而不是返回分配的二进制对象,因为这会泄漏C++因为没有垃圾回收

运算符 + 也应该采用常量引用。

此外,print、operator+ 和operator int 应该是 const 成员函数

此外,您不需要动态分配 128 个整数,只需将其设为 128 个整数的数组即可

private:
    int digits[128];

并删除数字上的删除

此外,您应该在构造函数中初始化它

memset(digits, 0, sizeof(digits));