C++ pointer syntax in class constructor leading to malloc error - c++

Background
I am self-learning C++ from this course, and I am unsure whether I understand why exactly my syntax was wrong.
Problem
Please see the two versions of the PointArray constructor in geometry_test.cpp. The first one gives an error, while the second one comes from the solution manual. In my (probably flawed) understanding, the two versions should be equivalent. Where have I gone wrong? When am I referring to the member attributes points and size? and when am I referring to the input variables points and size?
Thank you for any clarifications or suggestions to references I should check out.
Related query
How might the error message suggest a solution?
Code
geometry_test.h
class Point {
private:
int x, y;
public:
Point(int create_x = 0, int create_y = 0) { x = create_x; y = create_y; };
int getX() const { return x; };
int getY() const { return y; };
void setX(const int new_x) { x = new_x; };
void setY(const int new_y) { y = new_y; };
};
class PointArray {
private:
Point *points;
int size;
void resize(int n);
public:
PointArray(const Point points[], const int size);
~PointArray() { delete[] points; };
};
geometry_test.cpp
#include "geometry.h"
#include <iostream>
using std::cout;
PointArray::PointArray(const Point points[], const int size) { // breaks
points = new Point[size];
this->size = size;
for (int i = 0; i < size; ++i) { this->points[i] = points[i]; }
}
/*
PointArray::PointArray(const Point ptsToCp[], const int toCpSz) { // works
points = new Point[toCpSz];
size = toCpSz;
for (int i = 0; i < toCpSz; ++i) { points[i] = ptsToCp[i]; }
}
*/
int main() {
Point p1(1, 0);
Point p2(2, 0);
Point p3(1, 1);
Point ptarray[3] = {p1, p2, p3};
PointArray pa(ptarray, 3);
cout << p1.getX() << ", " << p1.getY() << "\n";
cout << p2.getX() << ", " << p2.getY() << "\n";
cout << p3.getX() << ", " << p3.getY() << "\n";
return 0;
}
Error message
geometry_test(17467,0x11b51adc0) malloc: *** error for object 0x7ffee4705690: pointer being freed was not allocated
geometry_test(17467,0x11b51adc0) malloc: *** set a breakpoint in malloc_error_break to debug
Abort trap: 6

Related

Deep copy unsuccessful

might be a stupid question and if it is, let me know, I will delete it as soon as possible. The thing is I have to make a deep copy in class "Kambarys" (ignore mixed languages, I know I shouldn't do that). Program terminates after trying to call function second time. Probably the problem is my syntax in constructor copy, but I can't find the correct one anywhere. One of the requirements is to create langas, durys and kambarys in dynamic memory using "new" and delete windows vector and door in Kambarys destructor. Appreciate the help!
Requirements:
In the main method, use the new operator to create room k1, add windows and doors to it. Write a constructor Room (const Room & k) that would create a correct copy. In the method main, write another room k2. Calculate the length of the baseboards / wall area.
Perform the following steps: k2 = * k1; delete k1;
#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;
class Langas{
private:
float height;
float widht;
static int countL;
public:
Langas(float h, float w){
this->height=h;
this->widht=w;
countL++;
}
~Langas(){
--countL;
}
float getHeight(){
return height;
}
float getWidht(){
return widht;
}
static int getWindowCount(){
return countL;
}
};
class Durys{
private:
float heightD;
float widhtD;
static int countD;
public:
Durys(float hD, float wD){
this->heightD=hD;
this->widhtD=wD;
countD++;
}
~Durys(){
--countD;
}
float getHeightD(){
return heightD;
}
float getWidhtD(){
return widhtD;
}
static int getDoorCount(){
return countD;
}
};
class Kambarys{
private:
float heightK;
float widhtK;
float lenghtK;
public:
vector<Langas*> windows;
Durys* door;
Kambarys(float hK, float wK, float lK){
this->heightK=hK;
this->widhtK=wK;
this->lenghtK=lK;
}
Kambarys(const Kambarys &k){
this->door=k.door;
this->windows=k.windows;
heightK=k.heightK;
widhtK=k.widhtK;
lenghtK=k.lenghtK;
}
~Kambarys(){
door=NULL;
for(int i=0; i<windows.size(); i++){
delete windows[i];
}
windows.clear();
delete door;
}
float getHeightK(){
return heightK;
}
float getWidhtK(){
return widhtK;
}
float getLenghtK(){
return lenghtK;
}
void addWindow(Langas* w){
windows.push_back(w);
}
void addDoor(Durys *d){
door=d;
}
};
float countWallPlot(Kambarys* k){
float cWPlot=(2*k->getLenghtK()*k->getHeightK())+(2*k->getWidhtK()*k->getHeightK());
for(int i=0; i<k->windows.size(); i++){
cWPlot-=((k->windows[i]->getHeight()))*(k->windows[i]->getWidht());
}
cWPlot-=((k->door->getHeightD()))*(k->door->getWidhtD());
return cWPlot;
}
float countLenght(Kambarys* k){
float floorL=(k->getLenghtK()*k->getWidhtK()*2);
floorL-=(k->door->getWidhtD());
return floorL;
}
int Langas::countL=0;
int Durys::countD=0;
int main(){
Langas *langas1=new Langas(3.4, 1.2);
Durys *durys=new Durys(3.1, 1.5);
Langas *langas2=new Langas(6.4, 1.5);
Kambarys *k=new Kambarys(30.4, 40.1, 50.1);
Kambarys *k2=k;
k->addWindow(langas1);
k->addWindow(langas2);
k->addDoor(durys);
cout<<countWallPlot(k)<<" "<<countLenght(k)<<endl;
cout<<"Window count "<<Langas::getWindowCount()<<", door count "<<Durys::getDoorCount()<<endl;
k2=k;
delete k;
cout<<countWallPlot(k2)<<" "<<countLenght(k2)<<endl;
cout<<"Window count "<<Langas::getWindowCount()<<", door count "<<Durys::getDoorCount()<<endl;
}
You have to allocate memory for k2 and copy the object, not the pointer.
You have to allocate memory in the copy constructor and copy assignment operator.
door=NULL; before delete door; would skip the delete and cause a memory leak.
windows.clear(); is not necessary in the destructor. Keep your code simple.
EDIT: After you added "Perform the following steps: k2 = * k1; delete k1;" I made k2 an object, not a pointer.
#include <iostream>
#include <vector>
class Langas {
private:
float height;
float width;
static int count;
public:
Langas(float h, float w): height(h), width(w) {
++count;
}
~Langas() { --count; }
float getHeight() const { return height; }
float getWidht() const { return width; }
static int getWindowCount() { return count; }
};
class Durys {
private:
float height;
float width;
static int count;
public:
Durys(float h, float w): height(h), width(w) {
++count;
}
~Durys() { --count; }
float getHeight() const { return height; }
float getWidth() const { return width; }
static int getDoorCount() { return count; }
};
class Kambarys {
private:
float height;
float width;
float length;
public:
std::vector<Langas *> windows;
Durys *door = nullptr;
Kambarys(float hK, float wK, float lK): height(hK), width(wK), length(lK) {}
Kambarys(const Kambarys &k): height(k.height), width(k.width), length(k.length), windows(), door(k.door ? new Durys(k.door->getHeight(), k.door->getWidth()) : nullptr) {
for (const auto window : k.windows) {
windows.emplace_back(new Langas(window->getHeight(), window->getWidht()));
}
}
Kambarys &operator=(const Kambarys &k) {
door = k.door ? new Durys(k.door->getHeight(), k.door->getWidth()) : nullptr;
for (const auto window : k.windows) {
windows.emplace_back(new Langas(window->getHeight(), window->getWidht()));
}
height = k.height;
width = k.width;
length = k.length;
return *this;
}
~Kambarys() {
for (auto window : windows) {
delete window;
}
delete door;
}
float getHeight() const { return height; }
float getWidth() const { return width; }
float getLength() const { return length; }
void addWindow(Langas *w) { windows.emplace_back(w); }
void addDoor(Durys *d) { door = d; }
};
float countWallPlot(const Kambarys &k) {
float cWPlot = 2 * k.getLength() * k.getHeight() + 2 * k.getWidth() * k.getHeight();
for (const auto window : k.windows) {
cWPlot -= window->getHeight() * window->getWidht();
}
cWPlot -= k.door->getHeight() * k.door->getWidth();
return cWPlot;
}
float countLength(const Kambarys &k) {
float floor = k.getLength() * k.getWidth() * 2;
floor -= k.door->getWidth();
return floor;
}
int Langas::count = 0;
int Durys::count = 0;
int main() {
Langas *langas1 = new Langas(3.4, 1.2);
Durys *durys = new Durys(3.1, 1.5);
Langas *langas2 = new Langas(6.4, 1.5);
Kambarys *k = new Kambarys(30.4, 40.1, 50.1);
Kambarys k2(*k);
k->addWindow(langas1);
k->addWindow(langas2);
k->addDoor(durys);
std::cout << countWallPlot(*k) << " " << countLength(*k) << std::endl;
k2 = *k;
std::cout << "Window count " << Langas::getWindowCount() << ", door count " << Durys::getDoorCount() << std::endl;
delete k;
std::cout << countWallPlot(k2) << " " << countLength(k2) << std::endl;
std::cout << "Window count " << Langas::getWindowCount() << ", door count " << Durys::getDoorCount() << std::endl;
}

Run-Time Check Failure #2 - Stack around the variable 'c2d' was corrupted. with c++

I'm studying for an exam and this is on my practice test. The question is "Which type of error does the following code fragment cause?"
Why is there an error?
struct C2D {
double x, y;
};
class Polygon {
int point;
C2D arr[];
public:
Polygon(int point_, C2D arr_[]) {
point = point_;
memcpy(arr, arr_, sizeof(C2D) * point);
};
void print() const {
for (int i = 0; i < point; i++) {
cout << arr[i].x << " " << arr[i].y << endl;
}
};
};
int main() {
C2D c2d[3];
c2d[0].x = 1;
c2d[0].y = 2;
c2d[1].x = 3;
c2d[1].y = 4;
c2d[2].x = 5;
c2d[2].y = 6;
Polygon p1(3, c2d);
p1.print();
return 0;
}
You didn't specify number of elements for the member
C2D arr[];
so there are no memory allocated for that.
You should use std::vector to allocate elements dynamically.
#include <iostream>
#include <vector>
#include <cstring>
using std::cout;
using std::endl;
struct C2D {
double x, y;
};
class Polygon {
int point;
std::vector<C2D> arr;
public:
Polygon(int point_, C2D arr_[]) : arr(point_) { // allocate point_ elements for arr
point = point_;
memcpy(arr.data(), arr_, sizeof(C2D) * point); // copy data using data()
};
void print() const {
for (int i = 0; i < point; i++) {
cout << arr[i].x << " " << arr[i].y << endl;
}
};
};
int main() {
C2D c2d[3];
c2d[0].x = 1;
c2d[0].y = 2;
c2d[1].x = 3;
c2d[1].y = 4;
c2d[2].x = 5;
c2d[2].y = 6;
Polygon p1(3, c2d);
p1.print();
return 0;
}

Accessing double pointer from another class

I'd like to access to a double pointer which is located in another class "Board".
class Board
{
public:
Board(void);
Board(unsigned int xSize, unsigned int ySize);
~Board(void);
void SetObjectManager(ObjectManager* pObm);
void SetBlock(Block* block);
void LoadBoard(void);
void InitBoard(void);
//Other Functions...
private:
ObjectManager* m_obm;
Block* m_block;
//pointer to pointer to a int. (for 2 dimensional-array)
int **m_board;
};
First, the Board class. at the last line of class, you can see m_board.
I want to change this value in outside of this class.
Like this,
void Block::InitBlock(void)
{
int randPiece = Random::GIRand().RandInt(0, 1);
int randPos = Random::GIRand().RandInt(0, 10);
switch (randPiece)
{
case 0:
m_piece[2][1] = 1;
m_piece[2][2] = 1;
m_piece[2][3] = 1;
m_piece[3][3] = 1;
break;
//Other cases are here...
}
std::cout << "RandPos : " << randPos << std::endl;
std::cout << "RandPiece : " << randPiece << std::endl;
for (int y = 0; y < m_ySize; ++y)
{
for (int x = 0, pX = randPos; x < m_xSize; ++x, ++randPos)
{
if (m_piece[x][y] != 0)
m_board->SetBoardStatus(randPos, y, 1);
}
}
}
But, When I run this program, It blows up at SetBoardStatus(int, int, int)
SetBoardStatus looks like this,
void Board::SetBoardStatus(int x, int y, int value)
{
m_board[x][y] = value; //Visual Studio breaks the program here.
}
I allocate the double pointer properly.
And I set the board at the outside of this classes.
void Block::SetBoard(Board* board)
{
m_board = board;
}
And this is my block class.
class Block
{
public:
Block(void);
~Block(void);
void SetObjectManager(ObjectManager* pObm);
void LoadBlock (void);
void InitBlock (void);
void UpdateBlock (void);
void ReleaseBlock (void);
void SetBoard(Board* board);
private:
ObjectManager* m_obm;
Board* m_board;
int **m_piece;
int m_xSize;
int m_ySize;
};
Consider inheriting Block in Board; This will eliminate any possible de-referencing errors or bugs, as you can access the pointer right away.

How do I pass in a vector of doubles to a constructor and then access its data in child classes (in C++)?

I want to be able to create not only a Chart, but a BarChart, and to pass in a vector of doubles and have that data put into the private member data. How would I do this in the BarChart (child) class of Chart? Also I am still confused as to pass by pointers, reference, or value, so I'm not sure if I am passing it correctly here. Please let me know how to fix this mess. Thank you for your help!
#include <vector>
using namespace std;
class Chart
{
public:
Chart(vector<double> &d) : data(d) {}
virtual void draw() const;
protected:
double value_at(int index) const; // ... only allows access, not modification
int get_size() const
{
return data.size();
}
private:
vector<double> &data; // Now data is safely private
};
class BarChart : public Chart
{
public:
virtual void draw() const
{
for (int x = 0; x < get_size() - 1; x++)
{
cout << value_at(x) << " ";
for (int y = 0; y < value_at(x); y++)
{
cout << "*";
}
cout << endl;
}
}
};
#include <iostream>
#include "chart.h"
#include <vector>
int main(int argc, char** argv)
{
vector<double> doubles;
doubles.resize(4);
for (int x = 0; x < 4; x++)
{
doubles[x] = x + 1.7;
}
BarChart c(doubles);
return 0;
}
I think this is what you want now. By the way you have to read these things for your future :)
How access modifiers works in inheritance
How constructors initialize in inheritance
What is the difference between pass by reference and pass by value.
These all you can read in the internet. Only thing is need to spend some time for find and read.
#include <vector>
#include <iostream>
class Chart
{
public:
Chart(std::vector<double> &d) : data(d) {}
virtual void draw(){}
double value_at(int index) const{ return data[index];}
int get_size() const{return data.size();}
private:
std::vector<double> &data;
};
class BarChart : public Chart
{
public:
BarChart(std::vector<double> &d):Chart(d)
{
}
virtual void draw()
{
for (int x = 0; x < get_size() - 1; x++)
{
std::cout << value_at(x) << " ";
for (int y = 0; y < value_at(x); y++)
{
std::cout << "*";
}
std::cout << std::endl;
}
}
};
int main()
{
std::vector<double> barchartData;
barchartData.push_back(10);
barchartData.push_back(20);
BarChart barchart(barchartData);
std::cout << "Barchart size :" << barchart.get_size() << std::endl;
std::vector<double> chartData;
chartData.push_back(500);
chartData.push_back(600);
Chart chart(chartData);
std::cout << "Chart size :" << chart.get_size() << std::endl;
return 0;
}

Inheritance with segmentation fault

I'm working on inheritance right now. I have a base class called Shape, and few others as sub class. There is no compilation error. But after when i enter all the coordinates, segmentation error pops out. Inside the driver class, option when when i tried using this d[count].toString();
Shape.h
class Shape
{
protected:
string name;
bool containsWarpSpace;
public:
Shape();
Shape(string, bool);
string toString();
virtual double computeArea();
void setName (string);
// some other codes here
};
Square.h
class Square : public Shape
{
protected:
int *x;
int *y;
int area;
int vertices;
public:
double computeArea();
void setSquare(string, string, int*, int*);
string toString();
};
Square.cpp
void Square::setSquare(string name, string type, int* a, int* b)
{
setName(name);
setContainsWarpSpace (type);
vertices = 4;
x = new int[vertices];
y = new int[vertices];
for (int i = 0; i < vertices; i++)
{
x[i] = a[i];
y[i] = b[i];
}
}
string Square::toString()
{
ostringstream convert;
string s;
string type;
for (int i = 0; i < vertices; i++)
{
convert << "point " << i + 1
<< " ( "
<< x[i] << " , " << y[i]
<< " ) "<< endl;
}
s = convert.str();
return s;
}
Driver class with int main()
class Driver
{
public:
Driver();
Shape *d[];
Square *s;
int count;
int noSquare;
int noRectangle;
int noCross;
void printDetails();
void printPlan();
void option1();
void option2();
void option3();
void option4();
string convertString(string);
};
Driver.cpp. This is the default constructor,
Driver :: Driver()
{
Shape d [MAX];
s = new Square [MAX];
count = 0;
int noSquare = 0;
int noRectangle = 0;
int noCross = 0;
}
Driver::option1()
{
if (shape.compare("square") == 0)
{
tempx = new int[4];
tempy = new int[4];
for (int i = 0; i < 4; i++)
{
int j = i + 1;
cout << "Please enter x-ordinate of pt " << j << ": ";
cin >>tempx[i];
cout << "Please enter y-ordinate of pt " << j << ": ";
cin >>tempy[i];
}
s[noSquare].setSquare(shape,type, tempx,tempy);
d[count] = &s[noSquare];
d[count].toString();
}
}
int main ()
{
option1();
}
Change the way you declared your shape in Driver class. In the header, declare it as :
Shape* d;
and in your CPP initialize it:
d = new Shape[MAX];
Also, since you are doing inheritance and arrays and pointers, you should manage your own destructors. Because if the chil object gets destroyed, it will take parent destructor. Therefore, your destructors should be:
virtual ~Shape();
And square:
virtual ~Square();
In them, delete the pointers:
delete x; // in case of square
delete y;
And when you have arrays:
delete [] d; // in case of driver class
Otherwise it will not free memory properly. That would probably fix your problems.