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

huangapple go评论72阅读模式
英文:

C++: pointer being freed was not allocated error when having an overloaded operator return a class

问题

以下是代码部分的翻译:

我正在尝试为我在C++中创建的类重载+运算符,但无论何时我在重载函数中返回新的类对象,都会出现以下错误:

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语句):

```cpp
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;
            // 将数据返回到主函数时,出现了错误

            return matrix;
        }
        void print();
    private:
        float *data;
        int length;
};

这是我主函数的一部分,我正在尝试调用它(A和B是之前定义的Matrix对象):

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

这是在主函数中调用的print()函数:

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

它说指针被释放但未分配,但我根本没有尝试释放任何已分配的数据--这个错误是什么意思,如何解决这个问题?如果答案很明显,我深感抱歉,我刚从C切换到C++,从未完全掌握指针和适当的数据分配。感谢您的一切建议!


希望这能帮助你理解问题并解决它。

<details>
<summary>英文:</summary>

I&#39;m trying to overload the + operator for a class I&#39;ve created in CPP, but whenever I return the new class object defined in the overloading function it gives me the error:

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

My class definition is this in the .h file for my program (with the necessary #includes and using statements at the top):

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 &lt; 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;

};

This is the part of my main function that I&#39;m trying to call (A and B are two other previously defined Matrix objects):

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

And this is the print() function being called in main():

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



It says that a pointer being freed was not allocated, but I&#39;m not at all attempting to free any allocated data--what does this error mean and what is a good way of going about fixing the problem?

Apologies if the answer is obvious, I&#39;ve only just switched from C to C++, and I never entirely got the hang of pointers and proper data allocation. Thank you for any and all advice!

</details>


# 答案1
**得分**: 3

错误在这里

```cpp
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()];

因为内存是动态分配的,所以在函数退出时不会被销毁,从而避免了这个特定的问题。

现在你可能还有许多其他问题(我还没有测试你的代码),而且你肯定存在内存泄漏的问题(正如你所说,你从不释放任何内存)。但我想这个问题留待将来解决。

英文:

The error is here

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

Firstly this is not even legal C++. In C++ array bounds must be constants, and trixIn.getLength() is not a constant. This construction is known as a variable length array or VLA, and some compilers accept it, but as I said, not legal C++, so on some compilers this code would not even compile. It is legal C however, which perhaps is why you are using it.

Having said that this code is bugged even on a compiler that accepts it. The VLA out1 only exists in the operator + that you have written. Once that function is exited the array is destroyed. But you have stored a pointer to that array in data. Therefore your Matrix class is left with a pointer to an array which no longer exists, this is called a dangling pointer and that causes your crash. In C++ you can never ignore the lifetime of objects, it's very easy to write code that points to or references objects that no longer exist.

The solution to both these issues is to use dynamic allocation

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

Because the memory is dynamically allocated it does not get destroyed when the function is exited and that particular problem is avoided.

Now you may have many other problems (I haven't tested your code), and you definitely do have the problem of leaking memory (as you said you never free any memory). But I guess that issue is for the future.

huangapple
  • 本文由 发表于 2023年2月24日 15:47:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/75553837.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定