This is my code:
linearMatrix lAmatrixmatrixmult(const linearMatrix &A,
const linearMatrix &B)
{
//Local variables
int W_A = A.Get_Width;
int H_A = A.Get_Height;
int H_B = B.Get_Height;
int W_B = B.Get_Width;
float *vectorA;
float *vectorB;
float *vectorC;
//================
//Memory allocation
try{
vectorA = new float[W_A * H_A];
}
catch(bad_alloc &ex)
{
cerr << "Exception:" << ex.what();
exit(1);
}
try{
vectorB = new float[W_B * H_B];
}
catch(bad_alloc &ex)
{
cerr << "Exception:" << ex.what();
exit(1);
}
try{
vectorC = new float[W_A * H_B];
}
catch(bad_alloc &ex)
{
cerr << "Exception:" << ex.what();
exit(1);
}
//=================
//Initialization
vectorA = A.Get_Vector;
vectorB = B.Get_Vector;
//==============
if(W_A == H_B)
{
linearMatrix C(W_A, H_B);
for(int i = 0; i < W_A; i++)
{
for(int j = 0; j < W_B; j++)
{
float sum = 0;
for(int k = 0; k < W_A; k++)
{
float a = vectorA[i * W_A + k];
float b = vectorB[k * H_B + j];
sum += a * b;
}
vectorC[i * W_A + j] = sum;
}
}
C.Set_Vector(vectorC, W_A, H_B);
//Free memory
delete [] vectorA;
delete [] vectorB;
delete [] vectorC;
//===========
return C;
}
else
{
cout << "Different sizes! Cannot perform mmmult" << endl;
//Free memory
delete [] vectorA;
delete [] vectorB;
delete [] vectorC;
//===========
exit(1);
}
}
And the ~linearMatrix is:
//Destructor definition
linearMatrix::~linearMatrix()
{
delete [] myVector;
}
Where linearMatrix is:
class linearMatrix
{
public:
//Constructor
linearMatrix(const int Width, const int Heigth);
//Copy constructor
linearMatrix(const linearMatrix &that);
//Copy assignment operator
linearMatrix& operator=(const linearMatrix& that);
//Destroyer
~linearMatrix();
//We read a matrix file
void Read_File_Matrix(const char *Path);
//We write a matrix file
void Write_File_Matrix(const char *Path);
//Generate a diagonal dominant matrix
void Generate_Diagonal_Dominant(void);
//Generate a random matrix
void Generate_Random_Matrix(void);
//Set a float *vector
void Set_Vector(const float *V, const int Width, const int Heigth);
//Show a little vector
void Show_Little_Matrix(void);
//Get the vector
//Suppose V is previously allocated
float *Get_Vector(void);
//Get total number of elements
int Get_NumberofElements(void);
//Get Width
int Get_Width(void);
//Get Height
int Get_Height(void);
private:
int myWidth, myHeight; // Width and Height
float* myVector;
//Aux function for testing
bool Test_Sizes(const int Width, const int Heigth);
};
Must I free memory before leaving a function if I used the new operator inside a function? Should I free memory before any exit() call?
No, that is not correct:
vectorA = new float[W_A * H_A]; // allocates memory
vectorA = A.Get_Vector(); // allocated memory is leaked
// vectorA now points to memory owned by A
delete [] vectorA; // delete memory owned by A
Of course, in C++ you would normally just use std::vector<float>.
Related
I'm trying to work with dynamic arrays. When I try to overload the "=" operator it does not work. When debugging the file it doesn't execute the void function to overload the operator.
#include <iostream>
using namespace std;
class cppArray {
public:
cppArray(int size);
~cppArray();
int read(int index);
void write(int content, int index);
void operator=(cppArray& s);
int search(int target);
int size();
private:
int* myArray;
int arraySize;
};
cppArray::cppArray(int size) {
myArray = new int[size];
arraySize = size;
}
//delete the memory space assigned to myArray
cppArray::~cppArray() {
delete[] myArray;
myArray = 0;
}
int cppArray::read(int index) {
if (index < arraySize) {
return myArray[index];
}
else {
cout << "Out of range" << endl;
exit(1);
}
}
Here I'm trying to copy the content of the original array to an auxiliar one, and then redefine the size of the original array so I can add more content to the original array
void cppArray::write(int content, int index) {
if (index < arraySize) {
myArray[index] = content;
}
else {
cppArray auxArray(arraySize);
auxArray.myArray = myArray;
delete[] myArray;
arraySize = index + 1;
myArray = new int[arraySize];
myArray = auxArray.myArray;
myArray[index] = content;
}
}
I'm pretty sure this is wrong, but I can't figure out a way to overload it correctly
void cppArray::operator=(cppArray& s) {
delete[] s.myArray;
s.myArray = new int[arraySize];
for (int i = 0; i < arraySize; i++)
{
myArray[i] = s.myArray[i];
}
}
int cppArray::size() {
return arraySize;
}
int main(int argc, char** argv) {
cppArray dsArray(3);
dsArray.write(1, 0);
dsArray.write(2, 1);
dsArray.write(3, 2);
dsArray.write(4, 3);
for (int i = 0; i < dsArray.size(); i++) {
cout << dsArray.read(i) << "\t";
}
cout << endl;
return 0;
}```
Your implementation is almost correct, but you delete the wrong array. You should only modify *this object, and not s. Also, you should follow conventions, or people will be very surprised when using your class.
Here's corrected version:
//return *this - a very expected convention
cppArray& cppArray::operator=(const cppArray& s) {
// Make sure s is not modified ^^^^
if (this == &s) {
return *this; //protection against self writing, things would get bad if you did that
}
arraySize = s.arraySize; //copy size first
delete[] myArray; //delete array from this object
myArray = new int[arraySize]; //recreate array
for (int i = 0; i < arraySize; i++)
{
myArray[i] = s.myArray[i]; //no changes here
}
return *this;
}
I'm very new to C++ so please excuse the sloppy code.
Here is the code in question:
Bag Class
class Bag {
protected:
Item* _myItems;
int _numItems;
int _size;
public:
Bag();
Bag(int size);
~Bag();
Bag(Bag& original);
void add(Item a);
void remove(int itemnum);
int size();
int numItems();
void operator=(Bag& bag);
Item& operator[] (int i);
};
//Empty constructor
Bag::Bag() {
_numItems = 0;
}
//overloaded constructor
Bag::Bag(int size) {
_numItems = 0;
_myItems = new Item[size];
}
//copy constructor
Bag::Bag(Bag& original) {
//Copies the numItems
_numItems = original._numItems;
//Makes a new copy of the original array
_myItems = new Item[_numItems];
//Copies each element of the original into the new
for (int i = 0; i < _numItems; ++i) {
_myItems[i] = original[i];
}
}
//Destructor
Bag::~Bag(){
delete[] _myItems;
}
//Returns the size of the bag
int Bag::size()
{
return _size;
}
//Returns the number of items in the bag
int Bag::numItems() {
return _numItems;
}
//Add a new item to the bag
void Bag::add(Item a) {
int s = _numItems;
//Create a Item pointer and assign it to the array of the bag
Item* temp = _myItems;
//Assign _myItems to a new, larger array
_myItems = new Item[_numItems++];
//Copy the old array into the new one and nullify all the old array's items
for (int i = 0; i < _numItems - 1; i++) {
_myItems[i] = temp[i];
}
//Destroy the old array
delete[] temp;
//Add the item to the last position
_myItems[_numItems] = a;
}
I am reading a text file line by line. The reading seems to be happening just fine. When I read in I execute this part of the code:
//The main program
int main() {
Pens * onePen = new Pens(1, 2);
Pens * twoPen = new Pens(2, 3);
Bag* bag = new Bag(5);
(*bag).add(onePen);
(*bag).add(twoPen);
bag[0];
bag[1];
int d = 0;
return 0;
}
I keep getting the Read Access Violation (This was 0xc) when I get into the add method. I also notice that when I put in breakpoints to examine the code, _numItems is not 0 but 211. Am I corrupting my memory somehow?
Here is a sample text file that we are using
Simplified version of the Bag and Pen classes (courtesy of PaulMcKenzie):
class Item {
protected:
int code_;
//Sets the method definition for the get/set methods and constructors
public:
Item(int code = -1);
virtual ~Item() {}
int getcode() const;
void setcode(int code);
std::ostream& operator<< (std::ostream& s);
bool operator== (const Item& a) const;
};
Item::Item(int code) : code_(code) {}
int Item::getcode() const { return code_; }
void Item::setcode(int code) { code_ = code; }
std::ostream & Item::operator<<(std::ostream& s)
{
s << " Code - " << code_ << "\n";
return s;
}
bool Item::operator==(const Item & a) const
{
return (code_ == a.getcode());
}
class Pens : public Item
{
private: int packetsize_;
public:
Pens();
Pens(int code, int packetsize);
int getpacketsize() const;
void setpacketsize(int packetsize);
bool operator== (const Pens& a) const;
};
Pens::Pens() :Item() { }
Pens::Pens(int code, int packetsize) : Item(code), packetsize_(packetsize) {}
int Pens::getpacketsize() const { return packetsize_; }
void Pens::setpacketsize(int packetsize) { packetsize_ = packetsize; }
std::ostream& operator<<(std::ostream& s, const Pens& pen)
{
s << " Packet size: " << pen.getpacketsize() << "\n";
return s;
}
bool Pens::operator==(const Pens & a) const
{
return code_ == a.getcode() && packetsize_ == a.getpacketsize();
}
I did not look in depth but this segment caught my eye:
//Add a new item to the bag
void Bag::add(Item a) {
int s = _numItems;
//Create a Item pointer and assign it to the array of the bag
Item* temp = _myItems;
//Assign _myItems to a new, larger array
_myItems = new Item[_numItems++];
//Copy the old array into the new one and nullify all the old array's items
for (int i = 0; i < _numItems - 1; i++) {
_myItems[i] = temp[i];
}
//Destroy the old array
delete[] temp;
//Add the item to the last position
_myItems[_numItems] = a;
}
Please look at this line:
_myItems = new Item[_numItems++];
You create new array with size of _numItems and then increase the _numItems by 1.
Which in my humble opinion leaves you with array of size _numItems-1.
And then you try to use element _myItems[_numItems] so this may be the reason of memory corruption.
when I try to set
cub.SetArray(cube);
I get an error
Console Application1.exe has triggered a breakpoint
What I'm doing wrong? When I try to debug cub -> cubesarray I get size -842150451. I don't understand why.Here's my all code
class Cube{
public:
static const int Change_ARRAY = 5;
private:
string color;
int size;
int *walls;
int n; // current size of array
int maximumsize; // maximum size of array
void Increase(int many);
public:
Cube(int maximumsize = 0);
~Cube();
void SetWalls(int wall);
void SetColor(string color);
void SetSize(int size);
string GetColor(){return color;}
int GetWalls(int i){return walls[i];}
int GetSize(){return size;}
int GetN(){return n;}
};
Cube::Cube(int maximumsize):n(0), maximumsize(maximumsize), size(size), walls(NULL){
if(maximumsize > 0){
walls = new int[maximumsize];
}
}
Cube::~Cube(){
if(walls){
delete [] walls;
}
}
void Cube::Increase(int many){
if(many > maximumsize){
int *newest = new int[many];
for(int i=0; i<n; i++)
newest[i] = walls[i];
delete [] walls;
walls = newest;
maximumsize = many;
}else if( many < maximumsize){
int *newest = new int[many];
for(int i=0; i<many; i++)
newest[i] = walls[i];
delete [] walls;
walls = newest;
n = maximumsize = many;
}
}
void Cube::SetWalls(int wall){
if(n == maximumsize) Increase(n + Change_ARRAY);
walls[n] = wall;
n++;
}
void Cube::SetColor(string color){
this->color = color;
}
void Cube::SetSize(int size){
this->size = size;
}
class CubesArray{
public:
static const int Change_Array = 5;
private:
Cube *cubesarray;
int currentsize; // current size of array
int maxsize; // maximumsize
void Change (int kk);
public:
CubesArray(int maxsize = 1);
~CubesArray();
void SetArray(Cube c);
Cube GetArray(int ind){return cubesarray[ind];}
int GetCsize(){return currentsize;}
};
CubesArray::CubesArray(int maxsize):cubesarray(NULL), currentsize(0), maxsize(maxsize){
if(maxsize > 0){
cubesarray = new Cube[maxsize];
}
}
CubesArray::~CubesArray(){
if(cubesarray){
delete [] cubesarray;
}
}
void CubesArray::Change(int kk){
if(kk > maxsize){
Cube *newarr = new Cube[kk];
for(int i=0; i<currentsize; i++)
newarr[i] = cubesarray[i];
delete [] cubesarray;
cubesarray = newarr;
maxsize = kk;
}if(kk < maxsize){
Cube *newarr = new Cube[kk];
for(int i=0; i<kk; i++)
newarr[i] = cubesarray[i];
delete [] cubesarray;
cubesarray = newarr;
currentsize = maxsize = kk;
}
}
void CubesArray::SetArray(Cube cub){
if(currentsize = maxsize) Change(currentsize + Change_Array);
cubesarray[currentsize] = cub;
currentsize++;
}
void Read(CubesArray & cub);
int main(){
CubesArray cub;
Read(cub);
system("pause");
return 0;
}
void Read(CubesArray & cub){
string color;
int size;
int i=0;
Cube cube;
ifstream fd(Data);
while(!fd.eof()){
fd >> color >> size;
cube.SetSize(size);
cube.SetColor(color);
cout << cube.GetColor() << " " << cube.GetSize() << " ";
while(fd.peek() != '\n' && !fd.eof()){
int w;
fd >> w;
cube.SetWalls(w);
cout << cube.GetWalls(i) << " ";
cub.SetArray(cube); // when I set cube to cub I get this error!!!
i++;
}
cout << endl;
fd.ignore();
}
}
Change:
if(currentsize = maxsize)
To:
if(currentsize == maxsize)
In addition, here is your real problem:
You have no copy-constructor in class Cube, so the walls array is not properly copied whenever you send a Cube instance by value, e.g., cub.SetArray(cube).
You must define it as follows:
Cube::Cube(const Cube& cube):n(cube.n),maximumsize(cube.maximumsize),size(cube.size),wall(NULL)
{
if (maximumsize > 0)
{
walls = new int[maximumsize];
for (int i=0; i<maximumsize; i++)
wall[i] = cube.wall[i];
}
}
And you have no assignment-operator in class Cube, so the walls array is not properly copied whenever you assign one Cube instance into another, e.g., cubesarray[currentsize] = cub.
You must define it as follows:
Cube& Cube::operator=(const Cube& cube)
{
n = cube.n;
maximumsize = cube.maximumsize;
size = cube.size;
wall = NULL;
if (maximumsize > 0)
{
walls = new int[maximumsize];
for (int i=0; i<maximumsize; i++)
wall[i] = cube.wall[i];
}
return *this;
}
BTW, in the copy-constructor, you can simply call the assignment-operator (remove coding redundancy):
Cube::Cube(const Cube& cube)
{
if (this != &cube)
*this = cube;
}
Your Cube class violates the rule of three. Look here:
void CubesArray::SetArray(Cube cub){ // calls copy constructor
That call creates a copy of your Cube class. Your Cube class is not safely copyable. Please see this and scroll down to the Managing Resources section: What is The Rule of Three?
You should pass Cube by reference or const reference, not by value. Doing so may correct the error you're having now, but still, your class is faulty.
I have a question concerning this code from Thinking in c++ book , this is a tiny c style library for learning the process of memory allocation , what does it mean to write
int startBytes = s->next * s->size;
in this code , what does this multiplication mean ?
//: C04:CLib.h
// Header file for a C-like library
// An array-like entity created at runtime
typedef struct CStashTag {
int size;
// Size of each space
int quantity; // Number of storage spaces
int next;
// Next empty space
// Dynamically allocated array of bytes:
unsigned char* storage;
} CStash;
void initialize(CStash* s, int size);
void cleanup(CStash* s);
int add(CStash* s, const void* element);
void* fetch(CStash* s, int index);
int count(CStash* s);
void inflate(CStash* s, int increase);
///:~
//: C04:CLib.cpp {O}
// Implementation of example C-like library
// Declare structure and functions:
#include "CLib.h"
#include <iostream>
#include <cassert>
using namespace std;
/ Quantity of elements to add
// when increasing storage:
const int increment = 100;
void initialize(CStash* s, int sz) {
s->size = sz;
s->quantity = 0;
s->storage = 0;
s->next = 0;
}
int add(CStash* s, const void* element) {
if(s->next >= s->quantity) //Enough space left?
inflate(s, increment);
// Copy element into storage,
// starting at next empty space:
int startBytes = s->next * s->size;
unsigned char* e = (unsigned char*)element;
for(int i = 0; i < s->size; i++)
s->storage[startBytes + i] = e[i];
s->next++;
return(s->next - 1); // Index number
}
void* fetch(CStash* s, int index) {
// Check index boundaries:
assert(0 <= index);
if(index >= s->next)
return 0; // To indicate the end
// Produce pointer to desired element:
return &(s->storage[index * s->size]);
}
int count(CStash* s) {
return s->next; // Elements in CStash
}
void inflate(CStash* s, int increase) {
assert(increase > 0);
int newQuantity = s->quantity + increase;
int newBytes = newQuantity * s->size;
int oldBytes = s->quantity * s->size;
unsigned char* b = new unsigned char[newBytes];
for(int i = 0; i < oldBytes; i++)
b[i] = s->storage[i]; // Copy old to new
delete [](s->storage); // Old storage
s->storage = b; // Point to new memory
s->quantity = newQuantity;
}
void cleanup(CStash* s) {
if(s->storage != 0) {
cout << "freeing storage" << endl;
delete []s->storage;
}
} ///:~
//: C04:CLibTest.cpp
//{L} CLib
// Test the C-like library
#include "CLib.h"
#include <fstream>
#include <iostream>
#include <string>
#include <cassert>
using namespace std;
int main() {
// Define variables at the beginning
// of the block, as in C:
CStash intStash, stringStash;
int i;
char* cp;
ifstream in;
string line;
const int bufsize = 80;
// Now remember to initialize the variables:
initialize(&intStash, sizeof(int));
for(i = 0; i < 100; i++)
add(&intStash, &i);
for(i = 0; i < count(&intStash); i++)
cout << "fetch(&intStash, " << i << ") = "
<< *(int*)fetch(&intStash, i)
<< endl;
// Holds 80-character strings:
initialize(&stringStash, sizeof(char)*bufsize);
in.open("CLibTest.cpp");
assert(in);
while(getline(in, line))
add(&stringStash, line.c_str());
i = 0;
while((cp = (char*)fetch(&stringStash,i++))!=0)
cout << "fetch(&stringStash, " << i << ") = "
<< cp << endl;
cleanup(&intStash);
cleanup(&stringStash);
} ///:~
It looks like it's getting the next free location by multiplying the size of the object by the index number of the next available space. So if the next space is 10, and the object size is 10, it will start allocating at byte index 100.
It is a straight multiplication of the values of next and size, I'm going to guess it's calculating an offset somewhere. From looking at the code, size is set by the sz parameter of the initialize function.
I've implemented a class named LipidType but the program crashes when the resize function and assignment operator overloading are called but I can't find out the error in the code. These are the private members of the class
private:
std::string *mod;
std::string *classe;
int matches;
double mz;
double *intensity;
double *frag;
std::string name;
int maxsize;
int length;
and these are the functions
LipidType& LipidType::operator=(const LipidType& otherlip) //assignment operator
{
if (this == &otherlip) return *this; // handle self assignment
if(otherlip.maxsize > maxsize)
{
std::cout << "Resizing" << std::endl;
resize(otherlip.maxsize);
}
for(int i=0; i<otherlip.length; i++)
{
mod[i]=otherlip.mod[i];
classe[i]=otherlip.classe[i];
intensity[i]=otherlip.intensity[i];
frag[i]=otherlip.frag[i];
}
matches=otherlip.matches;
name=otherlip.name;
mz=otherlip.mz;
length = otherlip.length;
return *this;
}
void LipidType::resize(int nusize)
{
maxsize = nusize;
std::string* temp1=new std::string[maxsize];
std::string* temp2=new std::string[maxsize];
double* temp3=new double[maxsize];
double* temp4=new double[maxsize];
for(int i=0; i<length; i++)
{
temp1[i]=mod[i];
temp2[i]=classe[i];
temp3[i]=intensity[i];
temp4[i]=frag[i];
}
delete [] mod;
delete [] classe;
delete [] intensity;
delete [] frag;
mod=temp1;
classe=temp2;
intensity=temp3;
frag=temp4;
}