I have the following class and code:
template <class T>
class HashTable {
struct Pair{
T element;
int key;
Pair(T element, int Key) : element(element), key(key) {};
};
int table_size;
int counter;
List<Pair> (*elements);
void changeTableSize(int newSize){
List<Pair> *temp = new List<Pair>[newSize];
for (int i = 0; i < table_size; i++){
for (typename List<Pair>::Iterator j = elements[i].begin(); j != elements[i].end(); j++){
Pair p = *j;
temp[p.key % newSize].insert(Pair(p.element, p.key));
}
}
delete[] elements;
elements = temp;
table_size = newSize;
}
public:
HashTable() : table_size(100), counter(0){
elements = new List<Pair>[table_size];
};
void insert(T data, int key){
if (member(key)){
throw ElementAlreadyExists();
}
elements[key % table_size].insert(Pair (data, key));
counter++;
if (counter == table_size){
changeTableSize(table_size*2);
}
};
When I call changeTableSize() the first time, everything is fine. When I call it the second time my program crashes saying "warning: HEAP: Free Heap block 006618C0 modified at 006618D4 after it was freed" right after the allocation for temp. What can cause this?
If originalSize > table_size then you are performing an illegal memory access in the inner 'for' loop.
Remove the 'originalSize' argument that you are passing to the function.
Use the class variable 'table_size' instead, and update it to the new size before you return.
Also, make sure that class Pair has a copy-constructor properly defined and implemented:
Pair(const Pair& pair)
{
// For each variable x of pair, that points to dynamically-allocated memory:
// this->x = new ...
// memcpy(this->x,pair.x,...)
// For each variable y of pair, that doesn't point to dynamically-allocated memory:
// this->y = pair.y
}
Otherwise, you might have two different instances of class Pair with internal variables pointing to the same dynamically-allocated memory. And when one instance is destroyed, the internal variables of the other instance will point to an already-freed memory.
Related
I created an array of pointers.
I want to know how to prp=operly add data to my array of pointers.
I have attempted the code below, unfortunately it is giving me a memory error and I do not know why.
class dataClass {
int data;
public:
void setdata(int d) {data = d;}
int getdata() const {return data;}
};
int main() {
dataClass** ptr = new dataClass*s[5];
int num = 9;
ptr[0] -> setdata(num);
return 0;
}
You just allocate the memory for the pointers (not for the objects), so ptr[0] points to an unspecified address and you get a segfault.
You need to add something like this:
for(int i = 0; i < 5; i++) {
ptr[i] = new dataClass;
}
When using a pointer-to-pointer-to-type, you must allocate storage for the required number of pointers and then allocate storage for each class which you then assign to each pointer.
For example, using 5 pointers as you attempt in your questions, you would first need to allocate for the pointers, e.g.
#define NPTRS 5
...
dataClass** ptrs = new dataClass *[NPTRS];
Now you have storage allocated for 5 pointers to type dataClass with the address for the initial pointer assigned to ptrs (I added the plural form for clarity)
The storage for the pointers is now allocated, but each of the allocated pointers does not yet point to valid storage for dataClass, they are just pointers. Before you can use the pointers to reference an instance of the class, you must allocate storage for each each class instance and then assign the address of the new block of memory to each of your pointers, e.g.
for (int i = 0; i < NPTRS; i++) {
ptrs[i] = new dataClass;
ptrs[i]->setdata (i+1);
}
(above you allocate storage for each class instance assigning the result to ptrs[i] and then set the data value to i+1)
Putting it altogether, you could do something similar to:
#include <iostream>
#include <cstdlib>
#define NPTRS 5
class dataClass {
int data;
public:
void setdata(int d) {data = d;}
int getdata() const {return data;}
};
int main() {
dataClass** ptrs = new dataClass *[NPTRS];
for (int i = 0; i < NPTRS; i++) {
ptrs[i] = new dataClass;
ptrs[i]->setdata (i+1);
}
for (int i = 0; i < NPTRS; i++)
std::cout << "ptrs[" << i <<"]->getdata() : "
<< ptrs[i]->getdata() << '\n';
return 0;
}
(note: don't forget you are responsible for keeping track of what you allocated and calling delete to free each allocation when it is not longer needed)
Example Use/Output
$ ./bin/dblptr2class
ptrs[0]->getdata() : 1
ptrs[1]->getdata() : 2
ptrs[2]->getdata() : 3
ptrs[3]->getdata() : 4
ptrs[4]->getdata() : 5
As others have mentioned, the C++ containers like vector are for less error prone and make your job a lot easier. Still, you should know how to handle both new/delete as well as the use of the containers.
Look things over and let me know if you have further questions.
You could first create an array of objects
(constructors will be called automatically).
After that create a pointer to your pointer:
#include <stdio.h>
class dataClass {
int data;
public:
dataClass(){
printf(" new instance \n");
}
void setdata(int d) {
data = d;
printf(" setdata \n");
}
int getdata() const {return data;}
};
int main() {
dataClass* ptr = new dataClass[5];
dataClass** pptr = &ptr;
int num = 9;
pptr[0]->setdata(num);
return 0;
}
result:
new instance
new instance
new instance
new instance
new instance
setdata
I am trying create my own vector, I am at the beginning, and when compile e execute the code, i get "Program not responding". This is the code:
struct X
{
X(){};
~X(){};
int v1, v2, v3;
};
template<typename T>
class Vector
{
public:
// constructors
Vector();
Vector(unsigned s);
virtual ~Vector();
// overloaded operators
T operator[](unsigned index);
// others
void clear();
void add(T value);
unsigned getSize();
bool isEmpty();
private:
// pointer to first item of memory block
T* first;
unsigned size;
};
template<typename T>
Vector<T>::Vector()
{
first = NULL;
size = 0;
}
template<typename T>
Vector<T>::Vector(unsigned s)
{
size = s;
first = new T[s];
};
template<typename T>
Vector<T>::~Vector()
{
clear();
}
template<typename T>
void Vector<T>::clear()
{
for(unsigned i = size ; i > 0 ; i--)
delete &first[i];
first = NULL;
}
template<typename T>
void Vector<T>::add(T value)
{
T* temp = new T[size + 1]; // error happens here
// copy data to new location
for(unsigned i = 0 ; i < size ; i++)
temp[i] = first[i];
// delete older data
clear();
// add the new value in last index
temp[size + 1] = value;
// update the pointer
first = temp;
size++;
}
template<typename T>
T Vector<T>::operator[](unsigned index)
{
return first[index];
}
template<typename T>
unsigned Vector<T>::getSize()
{
return size;
}
template<typename T>
bool Vector<T>::isEmpty()
{
return first == NULL;
}
int main(int argc, char* args[])
{
Vector<X> anything;
X thing;
anything.add(thing);
anything.add(thing);
anything.add(thing); // if remove this line, program work fine.
}
As I commented, error happens in T* temp = new T[size + 1];.
If i define the value of v1, v2, v3 of X class, e.g. X() : v1(0), v2(0), v3(0) { }, the program works correctly.
If i change the type, e.g., Vector of int, he works perfectly.
If put X class in std::vector, work fine too.
Other comments are also accepted.
Can someone helpme?
Your description of the problem is incredibly vague, but I can point out problems with your code:
No vector copy constructor (causes double-deletes and crashes)
No vector copy assignment (causes double-deletes and crashes)
clear is incorrectly calling delete (causes crashes and corruption) (you should match your single new of an array with a single delete of the array. Don't loop over elements.
add is writing past the end of the array (causes crashes and corruption)
add is not exception safe
You have to fix at least the first four. The third and fourth are probably the causes of your hang.
You have a buffer overflow occurring.
T* temp = new T[size + 1]; // When size is 0, you allocate 1 space.
You then assign to the temp array, but in location temp[1], which isn't a valid location because your array has only 1 element. This is undefined behavior, and that this point, your program is free to continue however it chooses. In this case, it seems to loop indefinitely.
// add the new value in last index
temp[size + 1] = value; // When size is zero, your array is length '1', but
// you are accessing temp[1] which is outside the
// bounds of your allocated memory.
i'm working on a array header from base definition of an array to create an array of any type with this header,so i created a array class with functions and constructors.
this is my code so far:
#include <iostream>
#define newline "\n"
class Arr
{
public:
typedef float T;
public:
Arr(int size);
Arr(int size, T fill);
T get(unsigned index) const;
void set(unsigned index, T newvalue);
unsigned Size() const;
unsigned SIZE;
void Print();
private:
};
Arr::Arr(int size,T fill)
{
SIZE = size;
T *pointer;
for (int i = 0; i < size; i++)
{
*pointer = fill;
pointer++;
}
}
void Arr::set(unsigned index, T newvalue)
{
T *pointer;
pointer = 0;
for (unsigned i = 0; i < index; i++)
{
pointer++;
}
*pointer = newvalue;
}
void Arr::Print()
{
T *pointer;
pointer = 0;
for (unsigned i = 0; i < SIZE; i++)
{
std::cout << *pointer << newline;
pointer++;
}
}
i know that my pointer point to nothing,as my question is my pointer should point to what to make this code work correctly?!
any time i point it to 0 after debug it crashes!
thanks...!
Pointers are tricky part of c++.
Here is a good link to get you started
http://www.codeproject.com/Articles/7042/How-to-interpret-complex-C-C-declarations
The reason your code doesn't work is a memory block for the array pointed to by the pointer is not allocated. You have to use the predecessor new in-order to achieve that.
Here an example
int size;
T arr;
T* ptr_2_arr;
ptr_2_arr = new T[size];
To retrieve elements of the array you can loop the array using a for loop
*ptr_2_arr[i];
hope this helps.
Post the problem statement if you need more detail
You must make a data member of the class that will point to the allocated memory for the array. Also you need to define a copy constructor, the copy assignment operator and the destructor.
Also it would be better that type of parameter size of constructors coinsides with the type of data member SIZE, I do not understand why this variable is written in capital letters.
ALso there is no any sense to make the data member SIZE and the function Size() public. if SIZE is public it can be changed by the user at any moment.
Make sure you specify the size of the array in your constructor.
SIZE = size;
pointer = new T[size]; //this is where I see an issue. Specify the size of your array.
for (int i = 0; i < size; i++)
{
*(pointer + i) = fill; //This is fine but you are filling up the array with only one number, fill. Nothing wrong with that if that is you intention. Try (*(pointer + i) = i; for i though size elements.
}
I have SquareMatrix defined as such
SquareMatrix.h
#ifndef SQUAREMATRIX_H
#define SQUAREMATRIX_H
#include "Matrix.h"
#include <vector>
class SquareMatrix : public Matrix
{
public:
SquareMatrix();
SquareMatrix(std::vector<std::vector<long double> >);
//~SquareMatrix(); //just in case there is dynamic memory explicitly used
//convenient member functions exclusive to SquareMatrix
bool isUpperDiagonalMatrix() const;
static SquareMatrix identityMatrix(unsigned);
void LUDecompose();
SquareMatrix *Lptr, *Uptr, *Pptr; //should be initialized by LUDecompose before using
protected:
void validateData();
private:
};
#endif // SQUAREMATRIX_H
and I am trying to set Lptr, Uptr (and maybe Pptr) with a call to SquareMatrix::LUDecompose(). It is defined below:
void SquareMatrix::LUDecompose()
{
unsigned rowCount = this->getRowCount();
//initialize L to identityMatrix
*this->Lptr = SquareMatrix::identityMatrix(rowCount);
//initialize U to sparse matrix with the first row containing the sole non-zero elements
std::vector<std::vector<long double> > UData(1, this->matrixData[0]); //making first rowVector the first rowVector of this
UData.insert(UData.end(), rowCount - 1, std::vector<long double>(rowCount,0)); //making all other rowVectors zero vectors
*Uptr = SquareMatrix(UData);
// attempting to perform LU decomposition
for (unsigned j = 0; j < rowCount; j++)
{
long double pivot = Uptr->matrixData[j][j];
//the pivot should be non-zero; throwing exception that should effectively cause function to return
if (pivot == 0)
throw MatrixArithmeticException(LU_DECOMPOSITION_FAILURE);
for (unsigned k = j+1; k < rowCount; k++)
{
if (j == 0)
{
//using *this to compute entries for L,U
this->Lptr->matrixData[k][j] = (this->matrixData[k][j])/pivot; //setting columns of L
long double multiplier = this->Lptr->matrixData[k][j];
//setting row of U
for (unsigned l = k; l < rowCount; l++)
{
Uptr->matrixData[k][l] = (this->matrixData[k][l])-multiplier*(this->matrixData[0][l]);
}
}
else
{
//using U to compute entries for L,U
//same procedure as before
this->Lptr->matrixData[k][j] = (Uptr->matrixData[k][j])/pivot;
long double multiplier = this->Lptr->matrixData[k][j];
for (unsigned l = k; l < rowCount; l++)
{
Uptr->matrixData[k][l] -= multiplier*(Uptr->matrixData[0][l]);
}
}
}
}
}
Upon trying to test out this function, it throws a segmentation fault at me, with the last line being the first line where I attempt to manipulate Lptr.
I attempt to change the object pointed by Lptr, and I know that I will not be able to reference the function and set the pointer equal to that reference. In other words, my compiler (GNU GCC compiler) will not allow this->Lptr = &SquareMatrix::identityMatrix(rowCount); as it will throw an -fpermissive type error.
Note: SquareMatrix::identityMatrix(unsigned) is defined as:
SquareMatrix SquareMatrix::identityMatrix(unsigned size)
{
std::vector<long double> rowVector(size, 0L);
std::vector<std::vector<long double> > identityMatrixData;
for (int i = 0; i < size; i++)
{
//setting the rowVector to zero-one vector
rowVector[i] = 1L;
if (i > 0) rowVector[i-1] = 0L;
//pushing rowVector into identityMatrixData
identityMatrixData.push_back(rowVector);
}
return SquareMatrix(identityMatrixData);
}
What do you think you CAN do about it?
I think I have two options:
throw the object on the heap, and then try to set it with the function (that would seem useless as you are redefining the object you just defined by throwing it on the heap)
get c++11 (or something similar)
Make the function a helper function that returns a std::vector<SquareMatrix*> of size two (containing pointers to the two desired SquareMatrix values), and create a function that calls the helper function and sets Lptr, Uptr to the respective elements of the returned vector.
Are my options this limited??
*Uptr = SquareMatrix(UData); in LUDecompose() is the problem.
You cannot set the pointer to an object that is being destroyed when the function returns. Then the pointer is a dangling pointer and whenever you attempt to use it, it'll segfault.
You need to do Uptr = new SquareMatrix(UData);. Then in your destructor, call delete Uptr;.
If you have access to C++11, you can use std::unique_ptr or any pointer containers/wrappers.
Examples of your options:
#include <memory>
class Matrix
{
public:
Matrix() {}
virtual ~Matrix() {}
};
class SqMatrix : public Matrix //using raw pointers. You must remember to delete your pointers.
{
private:
SqMatrix* UPtr = nullptr;
public:
SqMatrix() : Matrix() {}
void InitPtrs() {delete UPtr; UPtr = new SqMatrix();}
~SqMatrix() {delete UPtr;}
};
class OMatrix : public Matrix //No need to worry about clean up.
{
private:
std::unique_ptr<OMatrix> OPtr;
public:
OMatrix() : Matrix() {}
void InitPtrs() {OPtr.reset(new OMatrix());}
~OMatrix() {}
};
Another option is to just store it in a vector.
I'm a little bit confused on how to use correctly the delete keyword. Here is my scenario:
class Tuple {
public:
Tuple(int columns);
~Tuple();
void set(int i, string d);
string get(int i);
int columnCount();
private:
string *data;
int columns;
};
Tuple::Tuple(int columns) {
this->columns = columns > 0 ? columns : 0;
if (this->columns > 0) {
data = new string[this->columns];
} else {
data = 0;
}
}
Tuple::~Tuple() {
if (columns > 0) {
delete[] data;
}
}
void Tuple::set(int i, string d) {
if (columns > 0 && i > -1 && i < columns) {
data[i] = d;
}
}
class Table {
public:
Table(int columns);
~Table();
void insertTuple(Tuple t);
Tuple getTuple(int i);
int columnCount();
int rowCount();
private:
vector <Tuple> data;
int columns;
int rows;
};
Now, when I call the following code I get a segfault:
Tuple *outTuple;
outTuple = new Tuple(cCount);
for (int i=0; i<cCount; i++) {
tmpStr = string(reinterpret_cast<const char*>(sqlite3_column_text(statement, i)));
outTuple->set(i, tmpStr);
}
(*outTable)->insertTuple(*outTuple);
delete outTuple; //here I get segfault
What is wrong with my code? Is my code not well written? Can I improve it and avoid segfault?
The most likely reason is that the Tuple violates the rule of three. Specifically, you need to define a copy constructor and a copy assignment operator. Otherwise you are probably double-deleting data.
You don't show the constructor and the destructor, but memory management practices employed by Tuple look fragile. Why not use std::vector instead of a pointer?
Dynamically memory allocated variables with pointers, usually have a "container" or "owner".
In this case, the function is the main "container".
"Containtment" or "Ownership" may be transfer, example, from function to other variable, in this case, maybe "outTable".
Does the "outTable" deletes the tuple from memory ?
Are you intended to let "outTable" become the container of the tuple, and let it drop the tuple from memory, instead of the function ?
OR, do you intend that "outTable", only references the tuple, and, let the function drop the tuple from memory.
Cheers.