Get "Trigger Breakpoint Error at delete" when using template - c++

I'm using visual studio.
I have 3 class.
It's ok when I try to print Rectangle ABCD, but when i push ABCD into Array [rectangle] A and try to print ABCD again, the "wntdll.pdb not loaded" appear and i continue, it's "triggers breakpoint error!!" at delete in ~Rectangle()
I know it's something up to the pointer in class Rectangle but can't firgure out.
`int main(){
Array<Rectangle>A;
Rectangle a;
cout << a; //It's oke
A.PushBack(a); // problem here
cout<<a;
}`
class Point
{
private:
float _x;
float _y;
public:
float GetX() { return _x; }
float GetY() { return _y; }
public:
Point();
Point(float, float);
Point(const Point&);
~Point() {};
public:
string ToString() const;
public:
friend istream& operator>>(istream&, Point*);
friend ostream& operator<<(ostream&, const Point&);
};
Point::Point() {
_x = 1;
_y = 1;
}
Point::Point(float x, float y) {
_x = x;
_y = y;
}
Point::Point(const Point& a) {
_x = a._x;
_y = a._y;
}
string Point::ToString() const{
stringstream out;
out << "( " << _x << "," << _y << " )";
return out.str();
}
istream& operator>>(istream& in, Point* a) {
cout << "Nhap x: ";
in >> a->_x;
cout << "Nhap y: ";
in >> a->_y;
return in;
}
ostream& operator<<(ostream& out, const Point& a)
{
out << a.ToString();
return out;
}
```
class Rectangle
{
private:
Point* _topleft;
Point* _botright;
public:
void Set_topleft(Point tl) { _topleft = &tl; }
Point Get_topleft() { return *_topleft; }
void Set_botright(Point br) { _botright = &br; }
Point Get_botright() { return *_botright; }
public:
Rectangle();
Rectangle(Point*, Point*);
~Rectangle();
public:
string ToString() const;
public:
friend istream& operator>>(istream&, Rectangle&);
friend ostream& operator<<(ostream&, const Rectangle&);
};
Rectangle::Rectangle()
{
_topleft = new Point(0, 2);
_botright = new Point(3, 0);
}
Rectangle::Rectangle(Point* a, Point* b)
{
_topleft = new Point(*a);
_botright = new Point(*b);
}
Rectangle::~Rectangle()
{
delete _topleft;
delete _botright;
}
string Rectangle::ToString() const
{
stringstream out;
out << "A" << *_topleft << "+" << "D" << *_botright;
return out.str();
}
istream& operator>>(istream& in, Rectangle& a)
{
std::cout << "A( x,y ): ";
in >> a._topleft;
std::cout << "D( x,y ): ";
in >> a._botright;
return in;
}
ostream& operator<<(ostream& out, const Rectangle& a)
{
out << a.ToString();
return out;
}
```
template<class T>
class Array
{
private:
T* _a;
int _len;
public:
Array();
~Array();
public:
int length() { return _len; }
void PushBack(T);
T GetAt(int);
};
template<class T>
Array<T>::Array() {
_a = new T[128];
_len = 0;
}
template<class T>
Array<T>::~Array() {
delete[] _a;
_len = 0;
}
template<class T>
void Array<T>::PushBack(T value) {
if (_len >= 128)
{
std::cout << "Array is over size, which is 128\n";
return;
}
_a[_len] = value;
_len++;
}
template<class T>
T Array<T>::GetAt(int pos) {
return _a[pos];
}
```

The problem in your code is that when you PushBack the Rectangle object a into the array, you create copy of this object. This means that you just copy pointers _topleft and _botright. So in this part of code, you have 2 objects with the same pointers, so you're trying to delete twice the same part of memory.
To fix this you need to define own copy constructor, which will create new pointers in the new object.
Remember also to define own move constructors or make it disable for your class.
Rectangle(const Rectangle &other)
{
if(other._topleft)
_topleft= new Point(*other._topleft);
else
_topleft = nullptr;
if(other._botright)
_botright= new Point(*other._botright);
else
_topleft = nullptr;
}
The next problem is because of definition of void Array<T>::PushBack(T value). Please change it to the void Array<T>::PushBack(const T& value).
Also, try Rectangle(Rectangle&& o) = delete;

Related

Problem with Segmentation Fault with doing operations on class

Sorry for variables not being all in engilsh. I have a problem when i try to do the += operation on class called Uklad3.
It is initialized the same way as previous ones, but with this one the segmentation failure comes up when i try to do any operations on it.
Any sugestions how to fix it? I am not a proffesional programmer.
I sumbited the whole code because I know it might be little hard to read, I am learning and this is for ma class.
The goal of the operation += is to add points from one coordinate system to the other. It is only the portion of the task but this is where I have a problem.
class punkt
{
private:
double x;
double y;
double z;
public:
punkt(){};
string name;
punkt(string,double,double,double);
double getx() const {return x;}
double gety() const {return y;}
double getz() const {return z;}
};
punkt::punkt(string name_,double x_, double y_, double z_)
{
name=name_;
x=x_;
y=y_;
z=z_;
}
class Uklad
{
public:
static const int size = 10;
punkt tablica[size];
string uklad_name;
void add(punkt);
int licznik;
Uklad(){licznik=0;};
Uklad(string);
Uklad & operator+=(const Uklad &var)
{
for(int i=0;i<var.licznik;i++)
{
tablica[licznik]=var.tablica[i];
licznik++;
}
}
Uklad & operator-= (const Uklad &var)
{
for(int i=0;i<licznik;i++)
{
for(int j=0;j<var.licznik;j++)
{
if((tablica[i].getx()==var.tablica[i].getx()) and (tablica[i].gety()==var.tablica[i].gety()) and (tablica[i].getz()==var.tablica[i].getz()))
{
for(int k=i;k<licznik;k++)
{
tablica[k]=tablica[k+1];
}
licznik--;
}
}
}
}
};
Uklad::Uklad(string uklad_name_)
{
uklad_name=uklad_name_;
cout<<"Tworze uklad"<<endl;
}
void Uklad::add(punkt toAdd)
{
if(licznik<size)
{
tablica[licznik]=toAdd;
licznik++;
}
}
}
ostream & operator<<(ostream &s, const punkt &Punkt)
{
cout<<Punkt.name<<" "<<Punkt.getx()<<" "<<Punkt.gety()<<" "<<Punkt.getz();
return s<<" ";
}
ostream & operator<<(ostream &s, const Uklad &uklad)
{
for(int i=0;i<uklad.licznik;i++)
{
if(i==uklad.licznik-1) cout<<uklad.tablica[i]<<" ";
else
cout<<uklad.tablica[i]<<"; ";
}
return s<<" ";
}
int main()
{
//1.
string name1,name2,name3;
cin>>name1;
cin>>name2;
Uklad uklad1(name1);
Uklad uklad2(name2);
//2.
const int M=2;
double xtemp, ytemp, ztemp;
string nametemp;
string xs,ys,zs;
for(int i=0;i<M;i++)
{
cin>>nametemp;
cin>>xtemp;
cin>>ytemp;
cin>>ztemp;
punkt punktT(nametemp,xtemp,ytemp,ztemp);
uklad1.add(punktT);
}
//3.
const int N=2;
double xtemp2, ytemp2, ztemp2;
string nametemp2;
string xs2,ys2,zs2;
for(int i=0;i<N;i++)
{
cin>>nametemp2;
cin>>xtemp2;
cin>>ytemp2;
cin>>ztemp2;
punkt punktT2(nametemp2,xtemp2,ytemp2,ztemp2);
uklad2.add(punktT2);
}
//4.
cin>>name3;
Uklad uklad3(name3);
//5.
uklad3+=uklad1;
cout<<uklad3;
return 0;
}
static const int size = 10;
You make array about 10 size and after all this loops you go out of range of the array. That's why you have this error. You can give it higher size. Or you can use vectors. In case of using array you must be sure you will not go out of range.
I formated the code and add initializer to licznik. This code haven't segmentation fault error
class punkt
{
private:
double x;
double y;
double z;
public:
punkt(){};
string name;
punkt(string,double,double,double);
double getx() const {return x;}
double gety() const {return y;}
double getz() const {return z;}
};
punkt::punkt(string name_,double x_, double y_, double z_)
{
name=name_;
x=x_;
y=y_;
z=z_;
}
class Uklad
{
public:
static const int size = 10;
punkt tablica[size];
string uklad_name = "";
void add(punkt);
int licznik = 0;
Uklad(){licznik=0;};
Uklad(string);
Uklad& operator+=(const Uklad &var)
{
for(int i=0;i<var.licznik;i++)
{
cout << licznik << " += ";
tablica[licznik]=var.tablica[i];
licznik++;
}
return *this;
}
Uklad & operator-= (const Uklad &var)
{
for(int i=0;i<licznik;i++)
{
for(int j=0;j<var.licznik;j++)
{
cout << i << " -=";
if((tablica[i].getx()==var.tablica[i].getx()) and (tablica[i].gety()==var.tablica[i].gety()) and (tablica[i].getz()==var.tablica[i].getz()))
{
for(int k=i;k<licznik;k++)
{
tablica[k]=tablica[k+1];
}
licznik--;
}
}
}
return *this;
}
};
Uklad::Uklad(string uklad_name_)
{
licznik = 0;
uklad_name=uklad_name_;
cout << "Tworze uklad" << endl;
}
void Uklad::add(punkt toAdd)
{
if(licznik<size)
{
tablica[licznik]=toAdd;
licznik++;
}
}
ostream & operator<<(ostream &s, const punkt &Punkt)
{
cout<<Punkt.name<<" "<<Punkt.getx()<<" "<<Punkt.gety()<<" "<<Punkt.getz();
return s<<" ";
}
ostream & operator<<(ostream &s, const Uklad &uklad)
{
for(int i=0;i<uklad.licznik;i++)
{
if(i==uklad.licznik-1) cout<<uklad.tablica[i]<<" ";
else
cout<<uklad.tablica[i]<<"; ";
}
return s<<" ";
}
int main()
{
//1.
string name1,name2,name3;
cin>>name1;
cin>>name2;
Uklad uklad1(name1);
Uklad uklad2(name2);
//2.
const int M=2;
double xtemp, ytemp, ztemp;
string nametemp;
string xs,ys,zs;
for(int i=0;i<M;i++)
{
cin>>nametemp;
cin>>xtemp;
cin>>ytemp;
cin>>ztemp;
punkt punktT(nametemp,xtemp,ytemp,ztemp);
uklad1.add(punktT);
}
//3.
const int N=2;
double xtemp2, ytemp2, ztemp2;
string nametemp2;
string xs2,ys2,zs2;
for(int i=0;i<N;i++)
{
cin>>nametemp2;
cin>>xtemp2;
cin>>ytemp2;
cin>>ztemp2;
punkt punktT2(nametemp2,xtemp2,ytemp2,ztemp2);
uklad2.add(punktT2);
}
//4.
cin>>name3;
Uklad uklad3(name3);
//5.
uklad3+=uklad1;
cout<<uklad3;
return 0;
}

Why use a reference when returning an ostream class?

The full code looks like this:
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class Point {
double x;
double y;
public:
Point();
Point(int x, int y);
void setPoint(int x, int y);
int getX(void)const;
int getY(void)const;
Point operator + (const Point & point);
Point& operator=(const Point& point);
};
ostream& operator<<(ostream& os, const Point& point) {
os << point.getX() << " ," << point.getY();
return os;
}
Point::Point() {
x = y = 0;
}
Point::Point(int x, int y) {
this->x = x;
this->y = y;
}
void Point::setPoint(int x, int y) {
this->x = x;
this->y = y;
}
int Point::getX(void)const {
return this->x;
}
int Point::getY(void)const {
return this->y;
}
Point Point::operator+(const Point& point) {
Point result(this->x + point.getX(), this->y + point.getY());
return result;
}
Point& Point::operator=(const Point& point) {
this->x = point.getX();
this->y = point.getY();
return (*this);
}
int main() {
Point a(1, 2);
cout << a << endl;
}
In the following part
ostream& operator<<(ostream& os, const Point& point) {
os << point.getX() << " ," << point.getY();
return os;
}
If the return type is ostream, a red line appears. I am not sure what the difference between return type is ostream & and ostream. I'd appreciate it if you explained
*For reference, I forgot to return os, so I edited the post
If you would return an ostream then you would have slicing. In case the passed os was an ofstream then the returned ostream would only be the ostream part of the ofstream and not the full ofstream. When returning by reference you don't have slicing and don't lose information about the full type of the stream.
The ostream object cannot be copied as the copy constructor of ostream object is deleted.
That is why one needs to pass the ostream object by reference.
Pro tip: Ever wondered why we need to return ostream& if it was already passed by reference?

Why am i getting error: no match for ‘operator<<’ inside function?

Added override for operator<< for my class but i am getting inside a function:
error: no match for ‘operator<<’ (operand types are
‘std::basic_ostream’ and ‘Edge’)
cout << "Adding: " << edge;
But if i try to use this code everything works as expected:
Edge edge1("A", "B", 3);
Edge* edge2 = new Edge("A", "B", 3);
cout << edge1 << endl;
cout << *edge2 << endl;
Here is code:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Node {
public:
string name;
Node() {}
Node(string name):name(name) {}
bool operator==(const Node& other) {
return name == other.name;
}
};
class Edge {
public:
Node x;
Node y;
int cost;
Edge(string x_name, string y_name, int cost) {
this->x = Node(x_name);
this->y = Node(y_name);
this->cost = cost;
}
Edge(Node x, Node y, int cost):x(x),y(y) {}
bool operator==(const Edge& other) {
return x == other.x && x == other.y && cost == other.cost;
}
};
class Graph {
public:
vector<Edge> edges;
vector<Node> nodes;
bool has_node(Node node) {
return find(nodes.begin(), nodes.end(), node) != nodes.end();
}
bool has_edge(Edge edge) {
return find(edges.begin(), edges.end(), edge) != edges.end();
}
void add(string x_name, string y_name, int cost) {
Node x(x_name);
Node y(y_name);
bool has_not_x = !has_node(x);
bool has_not_y = !has_node(y);
if (has_not_x) {
nodes.push_back(x);
}
if (has_not_y) {
nodes.push_back(y);
}
if (has_not_x || has_not_y) {
add(x, y, cost);
}
}
void add(Node x, Node y, int cost) {
Edge edge(x, y, cost);
if (!has_edge(edge)) {
cout << "Adding: " << edge;
edges.push_back(edge);
}
}
};
ostream& operator<<(ostream& os, const Node& node)
{
os << "(" << node.name << ")";
return os;
}
ostream& operator<<(ostream& os, const Edge& edge)
{
os << edge.x << "-" << edge.cost << "-" << edge.y;
return os;
}
int main()
{
Graph* graph = new Graph();
graph->add("A", "C", 1);
return 0;
}
Because the compiler reads the code linearly, it is not aware that the overload of operator<<(ostream&, const Edge&) exists yet.
If you place a declaration of the overload before the definition of the class, the code will compile:
// Place the function declaration before the class
// to inform the compiler of the overload's existence.
ostream& operator<<(ostream& os, const Edge& edge);
class Graph {
public:
vector<Edge> edges;
vector<Node> nodes;
// and so on...

How to cout 'this' with overloaded output?

In the following example, how to refer to the current object instance to take opportunity to use the output overload?
class Shape {
private:
double _length, _width;
double straight(double value) {
if (value<0) { return -value; }
if (value==0) { return 1; }
return value;
}
public:
Shape() { setDims(1,1); }
Shape(double length, double width) {
setDims(length, width); }
void setDims(double length, double width) {
_length=straight(length); _width=straight(width); }
friend ostream &operator<<(ostream &output, Shape &S) {
output << S._length << "," << S._width; return output; }
void display() { cout << [THIS] << endl; }
};
int main(int argc, const char * argv[]) {
Shape s1; s1.display();
return 0;
}
Just like this:
void display() { cout << *this << endl; }
this is a pointer. Your operator<< wants an actual Shape object, not a pointer.
So you'll have to dereference the pointer first: *this.
Alternatively just use operator<<
#include <iostream>
using namespace std;
class Shape {
private:
double _length, _width;
double straight(double value) {
if (value<0) { return -value; }
if (value == 0) { return 1; }
return value;
}
public:
Shape() { setDims(1, 1); }
Shape(double length, double width) {
setDims(length, width);
}
void setDims(double length, double width) {
_length = straight(length); _width = straight(width);
}
friend ostream &operator<<(ostream &output, Shape &S) {
output << S._length << "," << S._width; return output;
}
int main(int argc, const char * argv[]) {
Shape s1;
std::cout << s1 << std::endl;
}

C++ noob: proper way to avoid redundant object copies when initializing? [duplicate]

This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 8 years ago.
I made a minimal example:
#include <iostream>
#include <conio.h>
using namespace std;
// skipped getters and setters and bounds checking for brevity
struct Vertex {
int x,y;
Vertex() {
}
Vertex(int x, int y) {
this->x = x;
this->y = y;
}
};
struct Polygon {
Vertex *vertexlist;
Polygon() {
}
Polygon(Vertex *v) {
vertexlist = new Vertex[4]; //hard coded 4 vertices for example brevity
for(int i=0;i<4;i++) {
vertexlist[i] = v[i];
}
}
Vertex& getVertex(int index) const {
return this->vertexlist[index];
}
};
struct PolyList {
Polygon *polylist;
int lastpoly;
PolyList() {
polylist = new Polygon[10]; //hard coded 10 for example brevity
lastpoly = 0;
}
void add(const Polygon& p) {
polylist[lastpoly++] = p;
}
};
ostream& operator<<(ostream& o, Vertex& v) {
return o << "(" << v.x << ", " << v.y << ")";
}
ostream& operator<<(ostream& o, const Polygon& p) {
for(int i=0;i<4;i++) {
o << p.getVertex(i) << ", ";
}
return o;
}
ostream& operator<<(ostream& o, PolyList& pl) {
for(int i=0;i<pl.lastpoly;i++) {
o << pl.polylist[i] << endl;
}
return o;
}
int someFunc() {
Vertex *vl = new Vertex[4];
PolyList pl;
vl[0] = Vertex(1,2);
vl[1] = Vertex(3,4);
vl[2] = Vertex(5,6);
vl[3] = Vertex(7,8);
pl.add(Polygon(vl)); // this Polygon goes out of scope after this line
cout << pl << endl;
}
int main() {
someFunc();
}
(So tl;dr, Polygon is a list of 4x Vertex, and PolyList is a list of Polygon:s. Polygon:s are add()ed to PolyList by instantiating a temporary Polygon)
Now, this leaks memory, because the Vertices in Polygon are never freed. However, if I add a destructor:
Polygon::~Polygon () {delete [] vertices}
then
cout << pl << endl;
will not work because the Polygon has gone out of scope and the destructor frees the vertices.
I could have the PolyList destructor call a Polygon->free() function. Alternatively, I could have the Polygon::Polygon(Vertex *v) deep copy all the vertices in v. Then PolyList::PolyList(Polygon &p) could deep copy p.
I could also make a PolyList::createPolygon(int x1, int y1, int x2, int y2...) but that flies in the face of OO.
What is the proper way to handle this kind of situation in C++? Never mind my actual example where a memory leak would not be a problem, I'm talking in principle. If I make an hierarchical object tree, I want to copy the pointers, not deep copy the objects.
EDIT: I'm trying to learn C++ on a deep level, so this is not about using vector<> or another "canned solution"; that is not what I'm after here, though I'm sure that is a good solution if the above example was an actual problem I was having. The example above is just the briefest example I could think of to explain my question.
You could use smart pointers and STL containers (mainly std::vector as suggested by PaulMcKenzie).
They will help a lot.
Your example using std::vector
#include <iostream>
#include <conio.h>
#include <vector>
using namespace std;
// skipped getters and setters and bounds checking for brevity
struct Vertex {
int x, y;
Vertex() {
}
Vertex(int x, int y) {
this->x = x;
this->y = y;
}
};
typedef vector<Vertex> vertex_list_t;
struct Polygon {
vertex_list_t vertexlist;
Polygon() {
}
Polygon(vertex_list_t v) {
//hard coded 4 vertices for example brevity
for (int i = 0; i<4; i++) {
vertexlist.push_back(Vertex(i, i));
}
}
Vertex getVertex(int index) const {
return vertexlist[index];
}
};
typedef vector<Polygon> polygon_list_t;
ostream& operator<<(ostream& o, Vertex& v) {
return o << "(" << v.x << ", " << v.y << ")";
}
ostream& operator<<(ostream& o, const Polygon& p) {
for (auto v: p.vertexlist) {
o << v << ", ";
}
return o;
}
ostream& operator<<(ostream& o, polygon_list_t& pl) {
for (auto &p : pl) {
o << p << endl;
}
return o;
}
int someFunc() {
vertex_list_t vl = {
Vertex(1, 2),
Vertex(3, 4),
Vertex(5, 6),
Vertex(7, 8)
};
polygon_list_t pl;
pl.push_back(Polygon(vl)); // this Polygon goes out of scope after this line
cout << pl << endl;
return 0;
}
int main() {
someFunc();
}
What's the real deal?
In the line
pl.add(Polygon(vl)); // this Polygon goes out of scope after this line
you pass the polygon as a temporary and:
$12.2/3- "Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created. This is true even if that evaluation ends in throwing an exception."
change that line by:
Polygon p1(vl);
pl.add(p1); // this Polygon NOT goes out of scope after this line
You can use shared_ptrs as the solution. i.e.
#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <memory>
#include <list>
#include <vector>
using namespace std;
struct Vertex
{
int x,y;
Vertex() : x(0), y(0)
{
}
Vertex(int _x, int _y)
{
x = _x;
y = _y;
}
};
struct Polygon
{
vector<Vertex> vertexes;
Polygon()
{
}
Polygon(Vertex *v)
{
const int ELEMS_COUNT = 4;
vertexes.reserve(ELEMS_COUNT);
vertexes.insert(vertexes.end(), v, v + ELEMS_COUNT);
}
Vertex getVertex(int index) const
{
return vertexes[index];
}
};
typedef shared_ptr<Polygon> PolygonPtr;
struct PolyList
{
std::list<PolygonPtr> polylist;
void add(PolygonPtr p)
{
polylist.push_back(p);
}
};
ostream& operator<<(ostream& o, const Vertex& v) {
return o << "(" << v.x << ", " << v.y << ")";
}
ostream& operator<<(ostream& o, const Polygon& p) {
for (auto& p : p.vertexes)
{
o << p << ", ";
}
return o;
}
ostream& operator<<(ostream& o, PolyList& pl) {
for(auto& p : pl.polylist)
{
o << *p << endl;
}
return o;
}
int someFunc() {
Vertex vl[] = {Vertex(1, 2), Vertex(3, 4), Vertex(5, 6), Vertex(7, 8)};
PolyList pl;
pl.add(PolygonPtr(new Polygon(vl)));
cout << pl << endl;
return 0;
}
int main()
{
someFunc();
return 0;
}