Destructor called after returning from function - c++

I've got some project for my University and I need to perform converting some data from file to matrix representation.
The main problem is that after returning form "returnNeighbours(int node)" destructor is called on neighbours object(as I concluded from running gdb).
I know that destructor is always called when local variable, in function, is initialized, but neihbours is a class member. I won't post everything, because it's not necessary I think. I've got some structures listed below.
representation.cpp
NodeContainer::NodeContainer(){ size = 0; array = nullptr; }
NodeContainer::~NodeContainer(){ size = 0; delete[] array; }
void NodeContainer::allocateMemoryAndSetSize(int n){ size = n; array = new int[size]; }
void MatrixRep::convertDataToMatrixRep(int** array)
{
for(int i = 0 ; i != size; i++)
for(int j = 0; j != size; j++)
matrix[i][j] = array[i][j];
}
NodeContainer MatrixRep::returnNeighbours(int node)
{
deleteNeighboursIfAny();
if(!checkIfNotBeyondMatrix(node))
return neighbours;
neighbours.allocateMemoryAndSetSize(countNeighbours(node));
for(int i = 0, j = 0; i < size; i++)
if(matrix[node-1][i] != 0)
{
neighbours.array[j] = matrix[node-1][i];
j++;
}
return neighbours;
}
void MatrixRep::deleteNeighboursIfAny(){ if(neighbours.array) neighbours.~NodeContainer(); }
bool MatrixRep::checkIfNotBeyondMatrix(int node)
{
if(node == 0 || node > size)
{
std::cerr<<"There is no such a node!\n";
return false;
}
else
return true;
}
int MatrixRep::countNeighbours(int node)
{
int count_non_zero = 0;
for(int i = 0; i != size; i++)
if(matrix[node-1][i] != 0)
count_non_zero++;
return count_non_zero;
}
representation.h
struct NodeContainer
{
int size;
int* array;
NodeContainer();
~NodeContainer();
void allocateMemoryAndSetSize(int);
};
class MatrixRep
{
int size;
NodeContainer neighbours;
int** matrix;
public:
MatrixRep(int);
~MatrixRep();
void convertDataToMatrixRep(int**);
NodeContainer returnNeighbours(int);
void deleteNeighboursIfAny();
bool checkIfNotBeyondMatrix(int);
int countNeighbours(int);
void setupMatrix();
void deleteMatrix();
};

If you would like to return a copy of NodeContainer, you must implement a copy constructor and assignment operator for it. If you're using a C++11 conformant compiler it will also be good to also implement a move constructor and move assignment operator as well.
On the other hand, if you would like to not create a copy, you must either return a pointer or a reference to the member. You could also make the member a std::shared_ptr, which you may return in this case.
However, in your current implementation you're actually returning a shallow copy of NodeContainer. Once your copy goes out of scope its destructor is called, which deallocates its memory, which in this case is the original memory of your member, effectively making your member invalid. The implementation is not good as it is. So, depending on your goal, either implement the first advised solution, or the second.

Related

passing pointer to function and using realloc

I want to pass a pointer to a function which will call a second function that will use realloc.
The issue is that realloc is returning NULL.
I don't know if the mistake is in the numbers of * in the function call or something else.
Could you please help me ?
The code:
int main(){
// some code.
clause_t* ptr; //clause_t is a structure i declared.
//Some work including the initial allocation of ptr (which is working).
assignLonely(matSAT, ic.nbClause, ic.nbVar, ptr); //the issue is here.
//Some other work
}
void assignLonely(int** matSAT, int nbClause, int nbVar, clause_t* ptr)
{
int i = 0, j = 0;
int cpt = 0;
int indice = -1;
for (i = 0; i < nbClause ; ++i)
{
j = 0;
cpt = 0;
while((j < nbVar) && (cpt < 2))
{
if (matSAT[i][j] != 0)
{
cpt++;
}
else
{
indice = j;
}
if (cpt < 2)
{
deleteClause(indice, &ptr);
}
j++;
}
}
}
void deleteClause(int indiceClause, clause_t** ptr)
{
int i = indiceClause;
int nbElt = sizeof((*ptr))/sizeof((*ptr)[0]);
int tailleElt = sizeof((*ptr)[0]);
while(i+1 < nbElt)
{
(*ptr)[i] = (*ptr)[i+1];
i++;
}
*ptr = (clause_t*)realloc(*ptr, (nbElt-1)*tailleElt);
if (*ptr == NULL)
{
fprintf(stderr, "Erreur reallocation\n");
exit(EXIT_FAILURE);
}
}
You have to declarae function assignLonely similarly to function deleteClause like
void assignLonely(int** matSAT, int nbClause, int nbVar, clause_t** ptr);
if you want that changes of ptr in the function would be stored in the original object in main.
Also take into account that this statement
int nbElt = sizeof((*ptr))/sizeof((*ptr)[0]);
is wrong.
Expression sizeof((*ptr)) will return the size of the pointer. Pointers do not keep information about how many elements in arrays they point to.
So expression
(nbElt-1)
can be equal to zero or even be negative.

Memory leaks from 2d array on heap

I'm having an issue with a lot of memory leaks from a class I've created. The assignment is requires creating a word search puzzle on the heap. I've created my destructor, copy constructor and overload the assignment operator.
I think there must be something wrong with one of these functions, because the final check to ensure it is working is to create objects in a loop, to see if it fails and my function is crashing. I've tried different forms of the destructor and I've tried changing around the copy and assignment operator with no luck. Kind of at a loss, and the lack of warnings is really making it difficult to debug without a proper understanding of the heap.
Any help would be really appreciated!
Here are some functions that are working with the heap.
JumblePuzzle::~JumblePuzzle(){
for (int i = 0; i < size; ++i){
delete jumble[i];
}
delete jumble;
}
JumblePuzzle::JumblePuzzle(string word, string diff){
int i = 0;
toHide = word;
difficulty = diff;
jumble = buildArray();
fillArray();
hideWord();
}
JumblePuzzle::JumblePuzzle(JumblePuzzle& temp){
size = temp.size;
rowPos = temp.rowPos;
colPos = temp.colPos;
direction = temp.direction;
toHide = temp.toHide;
difficulty = temp.difficulty;
jumble = temp.getJumble();
}
JumblePuzzle& JumblePuzzle::operator=(const JumblePuzzle& right){
if (this != &right){
for (int i = 0; i < size; ++i){
delete jumble[i];
}
delete[] jumble;
size = right.size;
rowPos = right.rowPos;
colPos = right.colPos;
direction = right.direction;
toHide = right.toHide;
difficulty = right.difficulty;
jumble = right.getJumble();
}
return *this;
}
charArrayPtr* JumblePuzzle::buildArray() const{
charArrayPtr* array = new char*[size];
for (int i = 0; i < size; ++i){
array[i] = new char[size];
}
return array;
}
Here's the line its failing on.
int loopLimit =20;
for (int i = 0; i < loopLimit; i++)
JumblePuzzle jp("HIDDENWORD", "hard");
Thanks for any possible help!
EDIT:
Here is my .h file as well.
#ifndef JUMBLE_H_
#define JUMBLE_H_
#include <time.h>
#include <cstdlib>
#include <string>
using namespace std;
typedef char* charArrayPtr;
class BadJumbleException {
public:
BadJumbleException(const string&);
string& what();
private:
string message;
};
class JumblePuzzle{
public:
JumblePuzzle(string, string); //simple constructor
JumblePuzzle(JumblePuzzle&); //copy constructor
~JumblePuzzle(); //deconstructor
charArrayPtr* getJumble() const;
JumblePuzzle& operator=(const JumblePuzzle&);
//accessors
int getSize();
int getRowPos();
int getColPos();
char getDirection();
private:
//attributes
int size;
int rowPos;
int colPos;
char direction;
charArrayPtr* jumble;
string toHide;
string difficulty;
void fillArray();
void hideWord();
char randomDirection();
int randomNum(int);
charArrayPtr* buildArray() const;
};
#endif
and my getJumble. It's used to get the actual word search created. Returned a copy rather than the pointer so it cant be modified.
charArrayPtr* JumblePuzzle::getJumble() const{
charArrayPtr* tempJumble = new char*[size];
for (int i = 0; i < size; ++i){
tempJumble[i] = new char[size];
}
for (int i = 0; i < size; i++){
for (int j = 0; j < size; j++){
tempJumble[i][j] = jumble[i][j];
}
}
return tempJumble;
}
There is one major thing wrong with your code, and that is you failed to initialize the "size" member in the JumblePuzzle(string, string) constructor.
There are other things you should do:
1) Create a separate function to destroy the 2d array within the JumblePuzzle class. You seem to be copying the same loops to do this in multiple places. No need for that if you just call a function to do this work.
2) Your assignment and copy constructor are not exception safe. If new[] throws an exception during the creation of the copy, then the original object has invalidated data. In other words, you've destroyed the data, and when you want to create another 2d array, when new[] says "oops", you've destroyed your original data and can't get it back.

Why does this code generate error?

I have a class that contains an array of another class called Sphere. Right now i am not sure why one part of code is generating an error.
.H file
sphere* list;
int listlen;
void add(sphere x);
sarray operator +(const sarray& arrayone);
.Cpp
sarray::sarray()
{
listlen = 0;
list = new sphere[200000];
}
sarray::~sarray()
{
delete [] this->list;
}
void sarray::add(sphere x) // Function for adding spheres to the list.
{
listlen++;
list[listlen-1] = x;
}
void sarray::operator = (const sarray& arrayone)
{
this -> list = NULL;
for(int i = 0; i < arrayone.listlen; i++)
{
this -> add(arrayone.list[i]);
}
}
sarray sarray::operator +(const sarray& arrayone)
{
sarray temparray;
for(int i = 0; i < arrayone.listlen; i++) // add all the elements from the first array to the temporary one
{
//sphere temp = arrayone.list[i];
temparray.add(arrayone.list[i]);
}
for(int j = 0; j < this -> listlen; j++)// add all the elements from the second array to the temporary one
{
temparray.add(list[j]);
}
return temparray;
}
The sphere class got a member variable called "Radius"
which when i try to compare like this
float a = 10;
for(int i=0; i > this->listlen;i++)
if(this->list[i].Radius > a) //<-- Can read the values
Works fine, but when change this part of the code
float a = 10;
sarray temparray = arrayone + *this;
for(int i = 0; i < temparray.listlen; i++)
if(temparray.list[i].radius > a) // Error comes here!
"Unhandled exception at 0x00138503: Access violation reading location"
while this doesent. I guess the problem is in the Add/operator function but i cant find it.
The following part looks problematic:
void sarray::add(sphere x) // Function for adding spheres to the list.
{
list[listlen-1] = x;
}
you should rather have something like this
void sarray::add(sphere x) // Function for adding spheres to the list.
{
list[listlen++] = x;
}
Also you should better have some error checking in add method.
OK, having looked at the destructor, you have a pointer to sphere in your sarray and has a destructor to destroy the pointer. This is all good except you haven't defined your own copy constructor which means the default copy constructor is used. In the function operator+ where you return temparray, a copy of the local copy is returned. The default copy constructor is called to create the copy. Then the local one will be destructed. Now the returned sarray copy's list will point to invalid data. You need to define your own copy constructor to make a deep copy of the list pointer.

Class creating multiple objects of another class at the same memory location (C++)

So, I've got this class that contains a vector of another class. Whenever I try to push a new object into this vector, it's creating that object at the same memory location each time.
The (hopefully) relevant code:
class FSM{
private:
std::vector<Node> nodeList;
int cap;
int obs;
int topNode;
public:
FSM(int nodeCap, int numObs){
cap = nodeCap;
obs = numObs;
topNode = -1;
}
bool addNode(){
if (isFull()) return false;
nodeList.push_back(Node(obs));
topNode++;
return true;
}
Now, if I create a stand-alone Node object in my main function and cout the &node, I get different memory locations. But the ones created in the FSM class are always the same. Also, if I change anything in one of the Nodes stored by the FSM class, it changes it for all of them. I have no idea what's going on.
EDIT: As requested, here is the Node class. Just gonna post the whole thing, not sure what is relevant.
class Node{
private:
std::vector<int> connects;
int action;
public:
Node(int numObs){
for(int i = 0; i < numObs; i++){
connects.push_back(-1);
}
srand(time(NULL));
}
void setConnections(std::vector<int> newVec){
for (int i = 0; i < connects.size(); i++){
connects[i] = newVec[i];
}
}
int getConnection(int index){
return connects[index];
}
std::vector<int> getConnectionList(){
return connects;
}
void setAction(int act){
action = act;
}
int getAction(){
return action;
}
void setRandomConnections(int numNodes){
for (int i = 0; i < connects.size(); i++){
connects[i] = rand() % numNodes;
}
}
};
EDIT the Second: Here's what my main is doing.
int main(){
FSM myFSM(5, 3);
while (!myFSM.isFull()){
myFSM.addNode();
std::cout << &myFSM.getTopNode(); // getTopNode() returns the most recent
// node.
}
}
If getTopNode does what I think it does, you're printing the address of a temporary object (aka a copy of the top node, not the top node itself). So that code is meaningless.
Here I've implemented a print function for the locations of the nodes in FSM:
void printNodeLocations()
{
for(Node& n : nodeList) { std::cout << &n << std::endl; }
}
And I get different ones as expected:
0x8ad3018
0x8ad301c
EDIT: I cannot reproduce your claim that changing one node changes all of them. See updated code
This line:
std::cout << &myFSM.getTopNode();
probably prints the address of a temporary object, not the actual object in the vector. This will be true if you're not returning by reference but rather by value.
So it's not weird if the temporary happens to be created at the same location each time, since after the temporary dies, its location in memory is free to be used again later.
In order to get the actual object rather than a copy of it, getTopNode() needs to do:
Node& FSM::getTopNode()
{
if (nodeList.empty()) {
// Up to you how to handle this error.
}
return nodeList.back();
}
Of course, if your current getTopNode() implementation actually already returns a pointer:
Node* FSM::getTopNode()
then your problem is that you're printing out the address of the pointer rather than the pointer itself. In that case you should print with:
std::cout << myFSM.getTopNode();
Nothing happens similar to yours.
#include <iostream>
#include <vector>
class Node{
private:
std::vector<int> connects;
int action;
public:
Node(int num){
for(int i = 0; i < num; i++){
connects.push_back(i);
}
}
std::vector<int> getConn()
{
return connects;
}
};
class FSM{
private:
std::vector<Node> nodeList;
public:
FSM(){}
void addNode(int size){
Node l(size);
std::cout<<"temp_address "<<&l<<"\n";
nodeList.push_back(l);//use of default copy constructor
}
void printList(){
std::vector<int> p;
for (int i=0; i<nodeList.size(); i++)
{
std::cout<<"Node_arr_num "<<i<<" mem_address "<<&nodeList[i]<<"\nConnections:";
p=nodeList[i].getConn();
for (int j=0; j<p.size(); j++)
std::cout<<" "<<p[j];
std::cout<<"\n";
}
}
};
int main()
{
FSM f;
f.addNode(5);
f.addNode(10);
f.addNode(3);
f.printList();
return 0;
}
Result:
temp_address 0xbfea7660
temp_address 0xbfea7660
temp_address 0xbfea7660
Node_arr_num 0 mem_address 0x8dab098
Connections: 0 1 2 3 4
Node_arr_num 1 mem_address 0x8dab0a8
Connections: 0 1 2 3 4 5 6 7 8 9
Node_arr_num 2 mem_address 0x8dab0b8
Connections: 0 1 2
Be careful with adding nodes later, when your app will grow. Temporary l object (ore your Node(obs)) must be copied with explicit copy constructor of class Node if Node will be more complex (contains fields with dynamic allocated memory).

Deallocation of an array of objects?

I'm having some issues deallocating arrays of a class I have. Below is the Class, a simplified implementation and my code I have tried to use to close it.
Characters class
#include <cstdlib>
class Character
{
private:
bool human;
int Xposition; // the character's postion on the board.
int Yposition; // the character's postion on the board.
bool alive;
public:
Character(); //This is my constructor
~Character(); //This is my destructor
bool isHuman(); //return whether type 1 aka Human
bool isZombie(); //return whether type 2 aka Zombie
void setHuman(); //set to type 1 or Human
void setZombie(); //set to type 2 or Zombie
void setPos(int xpos, int ypos); //set the board position
int X();
int Y();
bool isAlive(); //checks to see if a Human is still alive and to be displayed
bool Dead(); //kills the character and sets alive to false
int num_moves_allowed; //number of moves allowed.
};
Allocation code:
Character *characters[11];
int human_count = 0;
for(int i=0; i<12; i++)
{
characters[human_count] = new Character();
human_count++;
}
Termination code:
for(i=11;i<=0;i--)
{
if(characters)
{
characters[i]->~Character();
delete characters[i]; characters[i] = NULL;
}
}
if(characters)
{
//ERROR IS HERE
delete [] characters;
}
I have tried a number of different "delete" commands on the array and I keep getting an "Debug Assertion Failed!" window. It says that the dbgdel.cpp from visual studio vctools is the problem place on Line 52.
It also says "Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
Someone please help me I'm sure this is very simple.
I'd suggest you avoid using arrays all together. Use a vector of characters.
Declare your vector as
vector<Character> vCharacters;
then insert objects as
for(int i = 0; i < 100; i++)
vCharacters.push_back(Character());
If you want to store pointers to Character objects then wrap them in a shared_ptr which will take care of deallocating them for you.
vector<shared_ptr<Character>> vCharacters;
for(int i =0; i < 100; i++)
{
shared_ptr<Character> spCharacter(new Character());
vCharacters.push_back(spCharacter);
}
Avoid managing memory yourself when C++ can do it fo ryou
The characters array was allocated on the stack, so you don't have to delete it. However, if you want the array to survive the local scope, create it with something like this:
Character **characters = new Character[11];
then your delete[] line should work fine.
Also note that you don't need to call the destructor of Character explicitly: it is called automatically by delete.
As obelix mentioned, you should use a vector from the Standard Template Library.
However, if you're determined to use a raw array:
const int MAX_CHARACTERS = 11;
Character *characters[MAX_CHARACTERS];
for(int characterCount = 0; characterCount < MAX_CHARACTERS; ++characterCount)
{
characters[characterCount] = new Character();
}
...
if (characters != NULL)
{
for(int i = 0; i < MAX_CHARACTERS; ++i)
{
delete characters[i];
}
}
Paolo Capriotti is correct that characters should be declared with new if you want it to last beyond its scope:
const int MAX_CHARACTERS = 11;
Character **characters = new Character*[MAX_CHARACTERS];
for(int characterCount = 0; characterCount < MAX_CHARACTERS; ++characterCount)
{
characters[characterCount] = new Character();
}
...
if (characters != NULL)
{
for(int i = 0; i < MAX_CHARACTERS; ++i)
{
delete characters[i];
}
delete [] characters;
}
A better solution is the standard vector class:
#include <vector>
...
const int MAX_CHARACTERS = 11;
std::vector<Character> characters;
for (int i = 0; i < MAX_CHARACTERS; ++i)
{
characters.push_back(Character());
}
...
characters.clear();
Notice how much easier the cleanup was? (And in this case, it's optional, since when characters is destroyed it will automatically call the destructor of each item it contains.)
Also:
Character *characters[11];
should be
Character *characters[12];
and
for(i=11;i<=0;i--)
should be
for(i=11;i>=0;i--)
i realize this is a simplified use and all, but why bother with heap access at all?
just using
Character characters[11];
could be just as valid, and safe.
std::vector<> is nice, but if the list is always fixed size, and there's no heap involved in member data, why not?