【问题标题】:I get the error "free(): double free detected in tcache 2" while reading a file读取文件时出现错误“free(): double free detected in tcache 2”
【发布时间】:2021-12-01 19:13:54
【问题描述】:

当我尝试在不同于 Visual Studio Code 的任何 IDE 中编译我的代码时,我在读取文件后立即收到以下错误:

free():在 tcache 2 中检测到双重空闲。

当我删除析构函数时,程序运行良好,但“排序”函数将所有行输出为 [(0,0),(0,0)]。我不知道为什么会这样。如前所述,在 Visual Studio Code 中,程序从一开始就运行良好。这个问题有什么解决办法吗?我错过了什么吗?

这是我的代码和我正在使用的文件:

ma​​in.cpp

#include <fstream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cassert>
#include <iomanip>

#include "Line.hpp"
#include "Point.hpp"

using namespace std;

void inputLines(string filename, vector <Line>& Lines){

    ifstream inFS;

    inFS.open(filename);

    // checking if opened

    if (!inFS.is_open()){
        cout << "Couldn't open the input file" << endl << endl;
        return;
    }

    //lines:
    char letter1, letter2, letter3, letter4, letter5, letter6, d1;
    inFS >> letter1 >> letter2 >> letter3 >> letter4 >> letter5 >> letter6>> d1;

    //{[line1:[102.0,0.9],[97.0,1.0]],
    char d2, letterl, letteri, lettern, lettere, letter_1, d3, d4,d5 ,d6 ,d7 ,d8 ,d9 ,d10 ,d11 ,d12;
    double linep1x, linep1y, linep2x, linep2y;


    while (!inFS.eof()){

    inFS >> d2 >> letterl >> letteri >> lettern >> lettere >> letter_1 >> d3 >> d4
         >> linep1x >> d5 >> linep1y >> d6 >> d7 >> d8 >> linep2x >> d9 >> linep2y >> d10 >> d11 >> d12;


    if(!inFS.fail() && d2 == '[' && letterl == 'l' &&  letteri == 'i' &&  lettern == 'n' &&  lettere == 'e' &&  d3 == ':' &&  d4 == '[' &&  d5 == ','
                    && d6 == ']' &&  d7 == ',' &&  d8 == '[' &&  d9 == ',' &&  d10== ']' &&  d11 == ']' ){

                    Lines.push_back(Line(linep1x,linep1y,linep2x,linep2y));
            }
        }

        inFS.close();
    }

bool parallel(Line& line1, Line& line2){

double slope1 = line1.getSlope();
double slope2 = line2.getSlope();

if(slope1 == slope2){

    return true;
}

return false;

}


int main (){


cout <<"\n-----------------------------------------------\n"<< "           Starting unit testing ... " << "\n-----------------------------------------------\n\n";

//----------------------------------------------------------------------------------------------------------------------------------------


cout << "           ---------- | Testing setters and getters functions: | ----------\n\n";

Line l1_setGet;

cout << "We want to set a line with the coordinates (1,1)(2,2) and set the slope as 1.0 and the length as 1.41 \n\n";

Point p1_setGet(1,1);
Point p2_setGet(2,2);

l1_setGet.setPoint_1(p1_setGet);
l1_setGet.setPoint_2(p2_setGet);

l1_setGet.setSlope(1);
l1_setGet.setLength(1.41);

assert(l1_setGet.getLength() == 1.41);
assert(l1_setGet.getSlope() == 1);

cout << "All test passed...\n\n";

cout << "Line: " ; l1_setGet.print() ; cout << "\nSlope: " << l1_setGet.getSlope() << "\nLength: " << l1_setGet.getLength() <<"\n\n";

//----------------------------------------------------------------------------------------------------------------------------------------


cout << "         ---------- | Testing null constructors and assigning constructor: | ----------\n\n";

Point p1_constructor(-32.4,22.4);
Point p2_constructor(44.2,-31.9);


Line l1_constructor;
Line l2_constructor(p1_constructor, p2_constructor);


cout << "We want the first line to be initialized by the null constructor and the second line to be set by the other constructor \n\n";

cout << "Line 1: \n         ";
l1_constructor.print(); cout << "\n\n";

cout << "Line 2: [initialized with (-32.4,22.4) and (44.2, -31.9)]  \n         ";
l2_constructor.print(); cout << "\n\n";

cout << "Let's also test how the constructor calculates the length and the slope. For the second line the slope would be (-0.7) and the length would be (93.9):\n\n";

cout << "Slope: " << l2_constructor.getSlope() << "\n";
cout << "Length: " << l2_constructor.getLength() << "\n\n";

//----------------------------------------------------------------------------------------------------------------------------------------


cout << "         ---------- | Testing copy constructor and copy assignment operator: | ----------\n\n";

Point p1_copy(27.2,-29.3);
Point p2_copy(45.2, 11.9);

cout << "These are our test cases: \n\n";

Line l1_copy(p1_copy, p2_copy);
Line l3_copy;

cout << "         Line 1: "; l1_copy.print();  cout << "\n";
cout << "         Line 3: "; l3_copy.print();  cout << "\n\n";

cout << "Let's create and initialize the second line with the first line to test the copy constructor:\n\n";

Line l2_copy(l1_copy);

cout << "         Line 2: ";  l2_copy.print() ; cout << "\n\n";

cout << "Let's now use the assignment operator (=) to assign the second line to the third line:\n\n";

l3_copy = l2_copy;

cout << "         Line 3: ";  l3_copy.print() ; cout << "\n\n";

//----------------------------------------------------------------------------------------------------------------------------------------

cout << "         ---------- | Testing the parallel function: | ----------\n\n";

Point p1_para(2.0, 46.4);
Point p2_para(4.0, 88.8);

Point p3_para(2.0, 52.4);
Point p4_para(4.0, 94.8);

Point p5_para(2.0, -32.4);
Point p6_para(4.0, -74.8);

cout << "These are our test cases: \n\n";

Line l1_para(p1_para,p2_para);
Line l2_para(p3_para,p4_para);
Line l3_para(p5_para,p6_para);


cout << "         Line 1'slope: " << l1_para.getSlope();  cout << "\n";
cout << "         Line 2'slope: " << l2_para.getSlope();  cout << "\n";
cout << "         Line 3'slope: " << l3_para.getSlope();  cout << "\n\n";

cout << "Two lines are parallel when they have the same slope. Let's test the parallel function:\n\n";

cout << "Let's see if Line 1 and Line 2 are parallel: \n\n";

parallel(l1_para,l2_para) == 1 ? cout << "They are parallel\n\n" : cout << "They are not parallel\n\n";
assert(parallel(l1_para,l2_para) == 1);

cout << "Let's see if Line 1 and Line 3 are parallel: \n\n";

parallel(l1_para,l3_para) == 1 ? cout << "They are parallel\n\n" : cout << "They are not parallel\n\n";
assert(parallel(l1_para,l3_para) == 0);

cout << "All tests passed...\n\n";

//----------------------------------------------------------------------------------------------------------------------------------------

cout << "         ---------- | Testing the overloaded operators (< > ==): | ----------\n\n";

Point p1_oper(2, 2);
Point p2_oper(4, 4);

Point p3_oper(2, 2);
Point p4_oper(5, 5);

Point p5_oper(2, 2);
Point p6_oper(5, 5);

Point p7_oper(2, 2);
Point p8_oper(6, 6);



cout << "These are our test cases: \n\n";

Line l1_oper(p1_oper,p2_oper);
Line l2_oper(p3_oper,p4_oper);
Line l3_oper(p5_oper,p6_oper);
Line l4_oper(p7_oper,p8_oper);

cout << "         Line 1: " ; l1_oper.print();  cout << "     Length;  " << l1_oper.getLength() <<"\n";
cout << "         Line 2: " ; l2_oper.print();  cout << "     Length;  " << l2_oper.getLength() <<"\n";
cout << "         Line 3: " ; l3_oper.print();  cout << "     Length;  " << l3_oper.getLength() <<"\n";
cout << "         Line 4: " ; l4_oper.print();  cout << "     Length;  " << l4_oper.getLength() <<"\n\n";

cout << "       Let's test (<): \n\n";


cout << "(Line 1 < Line 2): ";
l1_oper < l2_oper == true ? cout << "True\n\n" : cout << "False\n\n";
assert( l1_oper < l2_oper == true );

cout << "(Line 2 < Line 1): ";
l2_oper < l1_oper == true ? cout << "True\n\n" : cout << "False\n\n";
assert( l2_oper < l1_oper == false );

//----------------------------------------------------------------------------------------------------------------------------------------


cout << "       Let's test (>): \n\n";


cout << "(Line 2 > Line 3): ";
l2_oper > l3_oper == true ? cout << "True\n\n" : cout << "False\n\n";
assert( l2_oper > l3_oper == false  );

cout << "(Line 4 > Line 1): ";
l4_oper > l1_oper == true ? cout << "True\n\n" : cout << "False\n\n";
assert( l4_oper > l1_oper == true );

//----------------------------------------------------------------------------------------------------------------------------------------

cout << "       Let's test (==): \n\n";


cout << "(Line 2 == Line 3): ";
l2_oper == l3_oper == true ? cout << "True\n\n" : cout << "False\n\n";
assert( l2_oper == l3_oper == true  );

cout << "(Line 1 == Line 4): ";
l1_oper == l4_oper == true ? cout << "True\n\n" : cout << "False\n\n";
assert( l1_oper == l4_oper == false  );
//----------------------------------------------------------------------------------------------------------------------------------------

cout << "All tests passed...\n\n";

cout << "         ---------- | Testing the file reader function: | ----------\n\n"; //--------------------------------------------------------------------


vector <Line> Lines;
string filename = "lines.txt";

cout << "Reading file...\n\n";

inputLines(filename, Lines);

cout << "Outputting extracted coordinates out of the file: \n\n";

for (int i = 0 ; i < Lines.size() ; i++){

Lines.at(i).print();

cout << endl;

}

cout << endl;

cout << "         ---------- | Testing the sort function: | ----------\n\n"; //--------------------------------------------------------------------

Lines.clear();

string filename_2 = "lines_2.txt";

cout << "Reading file with non-sorted values...\n\n";

inputLines(filename_2, Lines);

cout << "Outputting extracted coordinates out of the file: \n\n";

for (int i = 0 ; i < Lines.size() ; i++){

Lines.at(i).print();

cout << endl;

}

cout << endl;

cout << "Sorting... \n\n";

sort(Lines.begin(), Lines.end());

cout << "Outputting sorted values: \n\n";

for (int i = 0 ; i < Lines.size() ; i++){

Lines.at(i).print();

cout << endl;

}

cout << endl;

//----------------------------------------------------------------------------------------------------------------------------------------

Line l1_cout(1,2,3,4);

cout << "Overloading \"cout\" to print an object (in this case, a line with the coordinates (1,2),(3,4): \n\n";

cout << l1_cout << endl;

cout << endl;

//----------------------------------------------------------------------------------------------------------------------------------------


cout << "         ---------- | Testing the insertion operator (>> cin): | ----------\n\n";

Line l1_cin;

cout << "Enter a line in the format [(x1,y1),(x2,y2)] " << endl << endl;
cin >> l1_cin;

cout << "\nYou entered: " << endl << endl;
cout << "------- ";
l1_cin.print();
cout << " -------\n\n";

    return 0;
}

Line.hpp

#include <cmath>
#include "Point.hpp"
#include <iomanip>

using namespace std;

#ifndef LINE_H
#define LINE_H

class Line{

    private:

    Point* p1;
    Point* p2;

    double slope;
    double length;

    public:

    Line(); //null constructor
    Line(Point p1, Point p2);
    Line(double linep1x, double linep1y, double linep2x,  double linep2y);


// !accessors and mutators


//---------------------------------------//
    void setPoint_1 (double x, double y){
        p1->setX(x);
        p1->setY(y);
        
        calculateLength();
        calculateSlope();
    }

    void setPoint_1 (Point p){
        *p1=p;

        calculateLength();
        calculateSlope();
    }

    Point getPoint_1() const{
        return *p1;
    }

//---------------------------------------//

    void setPoint_2 (double x, double y){
        p2->setX(x);
        p2->setY(y);

        calculateLength();
        calculateSlope();

    }

    void setPoint_2 (Point p){
        *p2=p;
        
        calculateLength();
        calculateSlope();
    }

    Point getPoint_2() const{
        return *p2;
    }
//---------------------------------------//

    void setSlope(double s){
        this->slope = s;
    }

    void calculateSlope(){

    slope = ( (p2->getY()) - (p1->getY()) ) / ((p2->getX()) - (p1->getX()) );

    }

    double getSlope() const{
        return this->slope;
    }
//---------------------------------------//

    void setLength(double l){
        this->length = l;
    }

    void calculateLength(){

    length = sqrt( (pow( ( (p2->getX()) - (p1->getX()) ) , 2) ) + (pow(( (p2->getY()) - (p1->getY())), 2 ) ) );

    }

    double getLength() const{
        return this->length;
    }
//---------------------------------------//

//!print

void print() const;

//!destructor

~Line();

//!copy constructor
Line(const Line& l);

//!assignment
Line& operator=(const Line& line);

//! overloading operators

bool operator==(const Line& line);
bool operator<(const Line& line);
bool operator>(const Line& line);

friend ostream& operator<<(ostream& out, Line& L);
friend istream& operator>>(istream& in, Line& L);

};

#endif

Line::Line(){ //*null constructor

slope = 0;
length= 0;

p1 = new Point();
p2 = new Point();

}


Line::Line(double linep1x, double linep1y, double linep2x,  double linep2y){


p1 = new Point ;
p2 = new Point ;

p1->setX(linep1x);
p1->setY(linep1y);

p2->setX(linep2x);
p2->setY(linep2y);

//The distance between two points is given by d(P, Q) = √(x2 − x1)² + (y2 − y1)²

calculateLength();

//The slope of a line, given two points, is defined as  m = (y2-y1)/(x2-x1)

calculateSlope();

}

Line::Line(Point point1, Point point2){ //*overload constructor to calculate length and slope

double x1 = point1.getX();
double y1 = point1.getY();

double x2 = point2.getX();
double y2 = point2.getY();

p1 = new Point(x1,y1);
p2 = new Point(x2,y2);

//The distance between two points is given by d(P, Q) = √(x2 − x1)² + (y2 − y1)²

calculateLength();

//The slope of a line, given two points, is defined as  m = (y2-y1)/(x2-x1)

calculateSlope();

}

//*destructor

Line::~Line(){

delete p1;
delete p2;

}

//*copy constructor

Line::Line(const Line& line){

this->p1 = new Point ;
this->p2 = new Point ;

this->p1 = line.p1;
this->p2 = line.p2;

length = line.length;
slope = line.slope;

}

//*assignment operator

Line& Line::operator=(const Line& line){

    if(this!=&line){

        delete this->p1;
        delete this->p2;

        this->p1 = new Point ;
        this->p2 = new Point ;

        this->p1 = line.p1;
        this->p2 = line.p2;

    }

return *this;
}

// * =

bool Line::operator==(const Line& line){

    if(this->length == line.length){

        return true;
    }


   return false;
}



//* < operator

bool Line::operator<(const Line& line){

    if(this->length < line.length){

        return true;
    }

    return false;
}

//* > operator

bool Line::operator>(const Line& line){

    return (!(this->length < line.length) && !(this->length == line.length));
}


// * << operator (cout)

ostream& operator<<(ostream& out, Line& L){

out << "[(" << (L.p1->getX()) << ", " << (L.p1->getY()) <<"), (" << L.p2->getX() << ", " << (L.p2->getY()) <<")]";
    return out;
}

// * >> operator (cin)

istream& operator>>(istream& in, Line& L){

char d1, d2, d3, d4, d5, d6, d7, d8, d9;
double x1, y1, x2, y2;

        //[(x1,y1),(x2,y2)]
    in >> d1 >> d2 >> x1 >> d3 >> y1 >> d4 >> d5 >> d6 >> x2 >> d7 >> y2 >> d8 >> d9;


    if(!(d1 == '[' && d2 == '(' &&  d3 == ',' &&  d4 == ')' &&  d5 == ',' &&  d6 == '('  &&  d7 == ',' &&  d8 == ')' &&  d9 == ']' )){

                cout << "Invalid format" << endl;
            }
    else{

        L.setPoint_1(x1,y1);
        L.setPoint_2(x2, y2);
    }

return in;
}




//* print function

void Line::print() const{

cout << fixed << setprecision (1) << "[" << "(" << p1->getX()  <<", " << p1->getY() <<  ")" << "," << "(" << p2->getX() << ", " << p2->getY() << ")" << "]" ;

}

Point.hpp

#include <cmath>
#include <string>

using namespace std;

#ifndef POINT_H
#define POINT_H

class Point{

    private: // can only be used by public

        double x;
        double y;

    public:
    ///constructor
        Point (double X=0, double Y=0) : x(X), y(Y) {}

    //functions

        void setX(double x) {this->x= x ;}
        double getX() const {return this->x ;}

        void setY(double y) {this->y=y ;}
        double getY() const {return this->y ;}

        void print() const;

        friend bool operator== (Point lhp, Point rhp);
        friend bool operator> (Point lhp, Point rhp);
        friend bool operator< (Point lhp, Point rhp);

};


void Point::print() const{

    cout << "(" << this->x<< ","<<this->y<<")" << endl;


}


bool operator== (Point lhp, Point rhp){
    if((lhp.x == rhp.x && lhp.y == rhp.y)){
        return true;
    }
    else{
        return false;
    }
}


bool operator> (Point lhp, Point rhp){

    int euclideanLeft, euclideanRight;

    euclideanLeft = sqrt((pow(lhp.x, 2))+(pow(lhp.y,2)));
    euclideanRight = sqrt((pow(rhp.x, 2))+(pow(rhp.y,2)));

    if((euclideanLeft > euclideanRight)){
        return true;
    }
    else{
        return false;
    }
}


bool operator< (Point lhp, Point rhp){

   return !((lhp.x > rhp.x, lhp.y > rhp.y) || (lhp.x == rhp.x, lhp.y == rhp.y));

}

#endif

lines.txt

lines:
{
[line1:[102.0,0.9],[97.0,1.0]],
[line2:[103.0,0.8],[98.0,1.0]],
[line3:[104.0,0.7],[99.0,1.0]],
[line4:[105.0,0.6],[100.0,1.0]]
}

lines_2.txt

lines:
{
[line2:[103.0,0.8],[98.0,1.0]],
[line1:[102.0,0.9],[97.0,1.0]],
[line4:[105.0,0.6],[100.0,1.0]],
[line3:[104.0,0.7],[99.0,1.0]]
}

【问题讨论】:

  • Point* p1; Point* p2; -- 为什么是这些指针?看起来你在不存在任何问题时创造了一个问题。为什么这些不是简单的Point p1; Point p2;?
  • 欢迎来到 SO。看起来这里的大部分代码都是用于测试的。您应该删除所有这些并专注于问题。阅读如何创建minimal reproducible example。
  • 我正在使用指向类 Point 的指针,因为它是我作业的一部分。不过感谢大家的反馈。 “(a) 将私有数据成员 p1 和 p2 定义为指向 Point 对象(我们在讲座中使用的对象)的指针,将斜率和长度定义为双变量。”

标签: c++ oop runtime-error


【解决方案1】:

忽略 Line 没有真正理由保留指向 Points 的指针这一事实......

你的复制构造函数只是做一个浅拷贝,这意味着你最终会有多个 Line 实例指向相同的点:

Line::Line(const Line& line){

    this->p1 = new Point ;
    this->p2 = new Point ;

    this->p1 = line.p1; // this overwrites the newly allocated
    this->p2 = line.p2; // p1 and p2 above. 

    length = line.length;
    slope = line.slope;

}

应该是这样的:

Line::Line(const Line& line){

    this->p1 = new Point(line.p1->getX(), line.p1->getY());
    this->p2 = new Point(line.p2->getX(), line.p2->getY());

    length = line.length;
    slope = line.slope;

}

如果这不是针对需要 Line 中的 Points 作为指针的类,我真的建议您考虑仅将点存储在行中。它会解决很多令人头疼的问题。

【讨论】:

  • 哦,我明白了。非常感谢^^。你真的救了我的任务。是的,使用指向 Point 类的指针是我的作业的要求。我的教授希望我们习惯指针语法等:“(a) 将私有数据成员 p1 和 p2 定义为指向 Point 对象(我们在讲座中使用的那个)的指针,将斜率和长度定义为双变量。”
  • @RobertCabrera 在 SO 中说“谢谢”的一种好方法是投票和/或接受答案。
猜你喜欢
  • 2021-07-25
  • 1970-01-01
  • 1970-01-01
  • 2013-04-20
  • 2015-10-03
  • 1970-01-01
  • 2023-01-24
  • 2011-09-26
相关资源
最近更新 更多