C++:当重载运算符返回类时,出现释放指针未分配错误

ef1yzkbh  于 2023-02-26  发布在  其他
关注(0)|答案(1)|浏览(121)

我试图为我在CPP中创建的类重载+操作符,但是每当我返回重载函数中定义的新类对象时,它都会给我错误:

a.out(48371,0x10374a600) malloc: *** error for object 0x7ff7bf6525a0: pointer being freed was not allocated
a.out(48371,0x10374a600) malloc: *** set a breakpoint in malloc_error_break to debug
Abort trap: 6

我的类定义在我的程序的.h文件中是这样的(在顶部有必要的#includes和using语句):

class Matrix{
    public:
        Matrix(int);
        Matrix();
        ~Matrix();
        int getLength();
        float* getData();
        void readMatrix(string fileName);
        Matrix operator + (Matrix &trixIn) {
            Matrix matrix;
            float out1[trixIn.getLength()];                       
            
            float* dataA = trixIn.getData();
            float* dataB = data;

            for (int i = 0; i < trixIn.getLength(); i++){                 
                out1[i] = dataA[i] + dataB[i];         
            }

            matrix.length = trixIn.getLength();
            matrix.data = out1;
            // all this data up this point is correct when printed to the terminal

            return matrix;   // returning this to the main function brings up the error
        }
        void print();
    private:
        float *data;
        int length;
};

这是我试图调用的主函数的一部分(A和B是之前定义的另外两个Matrix对象):

Matrix C = A + B;
cout << "A + B with overload" << endl;
C.print();

这是main()函数调用的print()函数:

void Matrix::print(){
    for (int i = 0; i < length; i++){
       cout << std::setw(8) << data[i];  
    }
    printf("\n");
}

它说被释放的指针没有被分配,但是我根本没有尝试释放任何已分配的数据--这个错误意味着什么?解决这个问题的好方法是什么?
如果答案是显而易见的,我道歉,我只是刚刚从C转换到C++,我从来没有完全掌握指针和适当的数据分配。谢谢你的任何和所有的建议!

9lowa7mx

9lowa7mx1#

错误就在这里

float out1[trixIn.getLength()];
...
matrix.data = out1;

首先,这甚至不是法律的的C++。在C中,数组边界必须是常量,而trixIn.getLength()不是常量。这种结构被称为 * 可变长度数组 * 或VLA,一些编译器接受它,但正如我所说,不是合法的C,所以在一些编译器上,这段代码甚至不会编译。然而,它是合法的C,这可能就是为什么你要使用它。
这段代码即使在编译器上也有缺陷。VLA out1只存在于你写的operator +中。一旦退出这个函数,数组就会被销毁。但是你在data中存储了一个指向这个数组的指针。因此你的Matrix类只剩下一个指向一个不再存在的数组的指针。这就是所谓的“悬空指针”,它会导致崩溃。在C++中,你永远不能忽略对象的“生命周期”,编写指向或引用不再存在的对象的代码是非常容易的。
这两个问题的解决方案都是使用动态分配

float* out1 = new float[trixIn.getLength()];

因为内存是动态分配的,所以在函数退出时不会被破坏,从而避免了这个问题。
现在你可能有很多其他的问题(我还没有测试你的代码),你肯定有内存泄漏的问题(正如你所说,你从来没有释放任何内存),但我想这个问题是未来的。

相关问题