Segmentation fault when creating an array of objects - c++

Below is code that I am trying to get to work. I want to create an array of BankTeller objects. To my understanding when a new BankTeller() is called, it creates a pointer to that object, which I save into tellers. I then attempt to insert to that psotion but get segmentation fault when I use gdb to step through and the program crashes.
BankTeller **tellers;
BankModel(int count){
srand (time(NULL)); //ignore this
*tellers = new BankTeller[count];
for(int i=0; i <= count; i++){
tellers[i] = new BankTeller();
}
return;
}

I think your code is more complicated than it probably needs to be. I'd consider using std containers, like std::vector or whatever fits your needs better. Generally, you should avoid multiple levels of indirection unless it's really necessary, which in this case it does not appear to be.
Understanding Pointers
You began by declaring BankTeller **tellers, which is a pointer to a pointer to BankTeller. The line causing the segfault in your code is *tellers = new BankTeller[count];. This line returns a pointer to an array of BankTeller objects, but your declaration with the double ** says it should be getting an array to pointers to BankTeller objects. The value assigned is still interpreted as an address (which it isn't) and ends up trying to access an invalid memory location, which triggers the segfault.
Instead it should be *tellers = new BankTeller*[count];. Notice the * before the opening bracket. This line gets you an array of pointers to BankTeller objects.
Simple Example
To illustrate, forget about BankTellers and lets go back to primitives.
#include <iostream>
using namespace std;
int main()
{
const size_t max = 3;
int **nums;
cout << "Creating arrays...";
nums = new int*[max]; // <<---- not: nums = new int[max];
for(size_t i = 0; i < max; ++i)
nums[i] = new int(i);
cout << "done" << endl;
cout << "Contents: ";
for(size_t i = 0; i < max; ++i)
cout << *nums[i] << ' '; // <<---- dereferenced twice to reach actual value
cout << endl;
cout << "Deleting arrays...";
for(size_t i = 0; i < max; ++i)
delete nums[i];
delete[] nums;
cout << "done" << endl;
return 0;
}
Notice that this is the same situation described previously. To run it, put the code in a file called test.cpp and use this (GNU/Linux) command:
➜ /tmp g++ test.cpp -o test && ./test
Creating arrays...done
Contents: 0 1 2
Deleting arrays...done
➜ /tmp
If you want to go over it in the debugger, add -ggdb to the g++ command above to make sure you add debugging symbols to the binary. You can then use b <linenumber> (e.g. b 10) to setup a breakpoint and p <variable_name>, (e.g. p nums, p *nums, etc.) to print the addresses and values.
But again, you don't need to use raw pointers like this. You can, and should, use containers from the Standard Template Library.
Your Code Refactored
I've re-written the sample code below, using std::vector instead of double-pointers.
#include <iostream>
#include <vector>
using namespace std;
class BankTeller
{
public:
BankTeller() {
cout << "Created BankTeller\n";
}
~BankTeller() {
cout << "Destroyed BankTeller\n";
}
};
class BankModel
{
public:
BankModel(size_t count) {
// remember to throw exception if count <= 0
for(size_t i = 0; i < count; ++i)
_tellers.push_back(new BankTeller());
cout << "Created BankModel\n";
}
~BankModel() {
// consider using iterators
for(size_t i = 0; i < _tellers.size(); ++i) {
delete _tellers[i];
_tellers[i] = 0;
}
_tellers.clear();
cout << "Destroyed BankModel\n";
}
private:
vector<BankTeller*> _tellers;
};
int main() {
BankModel *model = new BankModel(5);
delete model;
return 0;
}
Building and running it in my system (GNU/Linux) looks as follows:
➜ /tmp g++ tellers.cpp -o tellers
➜ /tmp ./tellers
Created BankTeller
Created BankTeller
Created BankTeller
Created BankTeller
Created BankTeller
Created BankModel
Destroyed BankTeller
Destroyed BankTeller
Destroyed BankTeller
Destroyed BankTeller
Destroyed BankTeller
Destroyed BankModel
Hopefully, this helps you in understanding both pointers and the benefits of using the STL.

Your tellers variable is a pointer to a pointer. So when you do
*tellers = new BankTeller[count]
You have to make sure that memory has been properly allocated to a BankTeller*

Welcome to the dynamic arrays of C++! Correct way of writing this is:
BankTeller* tellers = new BankTeller[count];
You do not need a pointer to pointer for this.
However, do not do this at all! Use std::vector<BankTeller>

Try this -
BankTeller **tellers;
tellers = new BankTeller* [count];
for(int i=0; i <= count; i++)
{
tellers[i] = new BankTeller();
}
You can easily see the difference here.

Related

How to deallocate the dynamically allocated classes? [duplicate]

This question already has answers here:
C++ delete - It deletes my objects but I can still access the data?
(13 answers)
Closed 4 years ago.
I have this simple program below:
#include <iostream>
using namespace std;
class pithikos {
public:
//constructor
pithikos(int x, int y){
xPosition = x;
yPosition = y;
}
//multiplicator of x and y positions
int xmuly(){
return xPosition*yPosition;
}
private:
int xPosition;
int yPosition;
};
int main(void){
//alloccate memory for several number of pithikous
pithikos **pithik = new pithikos*[10];
for (int i = 0; i<10; i++){
pithik[i] = new pithikos(i,7);
}
cout << pithik[3]->xmuly() << endl; /*simple print statement for one of the pithiks*/
//create pithikos1
pithikos pithikos1(5,7);
cout << pithikos1.xmuly() << endl;
//delete alloccated memory
for (int i=0; i<10; i++) delete pithik[i];
delete [] pithik;
cout << pithik[4]->xmuly() << endl;
}
The class just takes two numbers and multiplies them and return the value.
But I want the oblects to born and die.
So I allocated in this example 10 objects (pithikos) and then I am testing weather it works.
when I ran the program I get this:
21
35
28
my problem is: why do I get the value 28 after I used the command?
delete [] pithik;
how can I delete the objects if not like this?
Always delete what you create with the new keyword. If you create an array of pointers using new keyword, use delete[] to delete all the pointer elements of the array.
how can I delete the objects if not like this?
This is the correct way of deleting the objects created with new keyword.
why do I get the value 28 after I used the command?
You should not deference a pointer after it is deleted. it results in an undefined behavior. You may get the old value or a nasty segmentation fault.
1-Calling delete will mark the memory area as free. It won't necessary reset its old value.
2-Accessing freed memory will surely cause you an undefined behavior so that's extremely inadvisable thing to try

Using shared_ptr to access addresses in vector to creat a linked list

Here, I am trying to make an array of nodes, which will also be linked as a linked list. I am purposely making the vector and linked list together, so as to make them contiguous, and when I pop from the vector, I can still refer to the memory.
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
struct node {
int data;
std::shared_ptr<node> next;
};
int main(){
vector<node> myArray;
for (int i = 0; i < 10; ++i) {
myArray.push_back(node());
}
for (int i = 0; i < 10; ++i) {
myArray[i].data = i;
myArray[i].next.reset(&myArray[i+1]);
}
std::shared_ptr<node> nodeList(make_shared<node>());
auto here = nodeList;
for (int i = 0; i < 10; ++i) {
here->next.reset(&myArray[i]); // the error occurs in this line
here = here->next;
}
here = nodeList;
here = here->next;
while (here != nullptr) {
cout << here->data << " with address of : " << &(*here) << endl;
}
return 0;
}
When I run this code, I get an error stating error for object 0x7fb8cbc033d0: pointer being freed was not allocated. Why is this happening? Thank you for your help in advance.
1) The pointer you assigned to myArray[i].next is not allocated by anyone, so it will barf when shared_ptr try to delete it.
2) myArray[i].next.reset(&myArray[i+1]); is dangerous, because the vector could reallocate the memory it uses, and this pointer will be invalid.
3) A linked list node doesn't have to store a pointer, you could store a next_index filed and do myArray[i].next_index = i + 1 or something like that.
4) You could also store shared_ptr in the vector if that's what you want.

Why one of those two similar functions crashes and one works ok?

This is really weird. If I increase the value of asize just by one crashSystem() does what its name speaks. Second function returning an int pointer works ok with much bigger values. Those two functions just delete and allocate the same dynamic array with same size (I created it just for test purposes).
Note: I think it could have something to do with maximum stack capacity 1MB (130037 * 8 in bytes is near 1MB), but it's really strange 'cause allocating using new inside function should work the same as any other new.
Using Visual Studio 2015
#include <iostream>
void crashSystem(int * dynamicArray, int asize) {
delete[] dynamicArray;
//dynamicArray = nullptr; does not matter at all
dynamicArray = new int[asize];
std::cout << "mem allocated\n";
}
int * worksOk(int * dynamicArray, int asize) {
int * newDynamicArray = new int[asize];
delete[] dynamicArray;
std::cout << "mem allocated\n";
return newDynamicArray;
}
int main()
{
int asize = 130037; // dynamic array size
//asize = 12330037; // for testing second function that works
int * dynamicArray;
dynamicArray = new int[asize];
for (int i = 0; i < 100; i++)
{
std::cout << "iteration " << i << " ";
crashSystem(dynamicArray, asize);
//dynamicArray = worksOk(dynamicArray, asize);
}
std::cout << "\n";
system("PAUSE");
}
Note 2: Crashing app this way in Release mode tends to block executable by creating non existent process (checked with Process Hacker 2)
The problem is that you're passing pointer by value, so it still points to the new int[asize]; allocated in main(), on which you then call multiple delete [].
It becomes a dangling pointer after the first delete [] call.
Even assigning nullptr won't help you if the pointer is not being passed by reference.
worksOk works, because you're returning the pointer pointing to the newly allocated space and assigning it, so it's valid every time.
Just change the signature so it uses reference:
void crashSystem(int *&dynamicArray, int asize)
and it should work fine.

How to correctly re-use pointer object to custom class

I have a lot of code so I am going to try to do this with as little as possible to show you guys.
I am writing a program that is leaking memory, my efforts of cleaning up memory is causing my program to crash (only in Visual Studio, not using MinGw). I am using Visual Studio 2015 to debug my code, and see how much memory I am using. However, when adding the delete keyword to try to free up some memory Visual Studio triggers a breakpont. When following the breakpoint to try and figure out whats wrong, VS takes me to a page that says 'No Source Available'.
Compiling this same code with MinGw gcc works find and executes fine, however I need Visual Studio's debugger so I can see my memory usage so that I can determine if the leak is fixed or not.
I am creating a lot of objects dynamically and re assigning new objects to them, I need help figuring out how to delete the old memory so I can only keep in memory the newly created object.
Here is the code that I am concerned with
StateNode *initState = nullptr; // Pointer to the initial state
StateNode *finishState = nullptr; // Pointer to the final state
bool finished = false; // Flag for checking if the puzzle has completed
size = getNumQueens();
// Make dynamic 2D array of the specified size
char** init = new char*[size];
for (int i = 0; i < size; i++)
init[i] = new char[size];
// Puzzle main loop
while (!finished)
{
// Randomize the queens placement on the board
randomizeGame(init, size);
// Make the initial state with the current game board
initState = new StateNode(init, size);
// Run the hillclimbing algo
finishState = HillClimbing<StateNode>::Run(initState, size);
// Check to see if the algo returned a valid end state
if (finishState->getHeuristic() == 0)
finished = true;
else
{
// Try to clean up memory to prevent memory leak
delete initState; // This is where Visual Studio throws breakpoint
delete finishState;
}
}
As you can see, this while loop constantly creates new StateNode objects by assigning them to initState. Also, the HillClimbing::Run() method returns a dynamically created StateNode and assigns it to finishState.
Without this code:
else
{
// Try to clean up memory to prevent memory leak
delete initState; // This is where Visual Studio throws breakpoint
delete finishState;
}
My program leaks a lot of memory, approaching 2GB when the program crashes.
With those lines VS throws breakpoints, but MinGw gcc does not, and the program works a lot faster.
My main question: How can I correctly manage the memory of initState and finishState to fix memory leaks.
i.e. How can I only keep in memory one StateNode object, while deleting all other instances as I go.
EDIT
This is what is in the VS output window
The thread 0x4244 has exited with code 1857355776 (0x6eb50000).
HEAP[N-Queens.exe]: Invalid address specified to RtlValidateHeap( 01230000, 0126B540 )
N-Queens.exe has triggered a breakpoint.
When going into the dissasembly and pressing F11 to keep going through the code, eventually this happens:
EDIT 2
StateNode.h
class StateNode
{
private:
char** state;
int heuristic;
int size;
public:
StateNode(char** state, int size);
int getHeuristic();
void printState();
char** getState();
};
Here is the code for StateNode.cpp
#include <iostream>
#include "state-node.h"
#include "heuristic.h"
/* Constructor, accepts a state and a size (the number of queens) */
StateNode::StateNode(char ** state, int size)
{
this->state = state;
this->size = size;
this ->heuristic = NQueens::CalcHeuristic(state, size);
}
/* Returns the heuristic value of the node */
int StateNode::getHeuristic()
{
return this->heuristic;
}
/* Prints the state with a nice like board for better visualization */
void StateNode::printState()
{
for (int i = 0; i < this->size; i++)
std::cout << " ____";
std::cout << std::endl;
for (int i = 0; i < this->size; i++)
{
for (int j = 0; j < this->size; j++)
{
if (j < this->size - 1)
{
std::cout << "| " << state[i][j] << " ";
}
else
{
std::cout << "| " << state[i][j] << " |";
}
}
std::cout << std::endl;
for (int k = 0; k < this->size; k++)
std::cout << "|____";
std::cout << "|\n";
}
}
/* Returns a copy of the nodes state */
char ** StateNode::getState()
{
return state;
}
Your current code allocates dynamically allocated memory, but doesn't have a coherent sense of who owns what pointer(s). It then becomes cumbersome to figure out when, where, and who is responsible for freeing the memory. To fix such code may require more error-prone logic to figure to attempt to straighten out the mess.
Instead of this, using C++ and "new-less" code, the following is more or less the equivalent of your current code:
#include <vector>
typedef std::vector<std::vector<char>> Char2D;
class StateNode
{
private:
char2D state;
int size;
int heuristic;
public:
StateNode(const Char2D& theState, int theSize);
int getHeuristic();
void printState();
Char2D& getState() { return state; }
};
Then your constructor lools like this:
StateNode::StateNode(const Char2D& theState, int theSize) :
state(theState),
size(theSize),
heuristic(NQueens::CalcHeuristic(state, size)) {}
Of course, your NQueens::CalcHeuristic has to take a Char2D (by reference) instead of a char**.
Then the rest of the implementation can look like this:
bool finished = false;
size = getNumQueens();
// Make dynamic 2D array of the specified size
Char2D init(size, std::vector<char>(size));
// Puzzle main loop
while (!finished)
{
// Randomize the queens placement on the board
randomizeGame(init, size);
// Make the initial state with the current game board
StateNode initState(init, size);
// Run the hillclimbing algo
finishState = HillClimbing<StateNode>::Run(initState, size);
// Check to see if the algo returned a valid end state
if (finishState.getHeuristic() == 0)
finished = true;
}
The initState and finishState are two distinct objects. Also, no need for the else block.
I know this is somewhat different than your original code, but the goal should be to use value types and if need be, smart pointers (which I didn't see a need here). Using types as the aforementioned ones is one way to not have issues as your facing now.
If you still want to go the pointer route, I would still leave the vector alone, and make the following changes:
#include <memory>
//...
std::unique_ptr<StateNode> finishState;
// Puzzle main loop
while (!finished)
{
// Randomize the queens placement on the board
randomizeGame(init, size);
// Make the initial state with the current game board
std::unique_ptr<StateNode> initState = std::make_unique<StateNode>(init, size);
// Run the hillclimbing algo
finishState.reset(HillClimbing<StateNode>::Run(initState, size));
// Check to see if the algo returned a valid end state
if (finishState->getHeuristic() == 0)
finished = true;
}
There is no leak in this code, as we are using std::unique_ptr, which automatically deallocates the memory for you when either the pointer goes out of scope, or reset is called.
You can debug through no-source-available into your code. Get vs to show disassembly and f11 into next function.
Vs has debug heap with leak detection. That can help, but also cause slow down, and earlier crash. Compile with different C runtime to gain/lose that feature.
Application verifier also has good leak detection, showing stacks of leaked allocations. this is what I use

What is wrong with my park_car function?

I'm again doing a task for school and I'm implementing it slowly, I don't know why my park_car function is not working, I just wanted to make a test and the program crashes ... here is my code.
PS: I can't change the ***p2parkboxes because it is given in the starter file like most other variables. I just want to see the first element of Floor 0 as : HH-AB 1234. Your help is most appreciated.
PS2: I can't use the std::string as well it isn't allowed for the task.
#include <iostream>
#include <cstring>
using namespace std;
#define EMPTY "----------"
class Parkbox{
char *license_plate; // car's license plate
public:
Parkbox(char *s = EMPTY); // CTOR
~Parkbox(); // DTOR
char *get_plate(){return license_plate;}
};
class ParkingGarage{
Parkbox ***p2parkboxes;
//int dimensions_of_parkhouse[3]; // better with rows,columns,floors
int rows,columns,floors; // dimensions of park house
int total_num_of_cars_currently_parked;
int next_free_parking_position[3];
// PRIVATE MEMBER FUNCTION
void find_next_free_parking_position();
public:
ParkingGarage(int row, int col, int flr);// CTOR,[rows][columns][floors]
~ParkingGarage(); // DTOR
bool park_car(char*); // park car with license plate
bool fetch_car(char*); // fetch car with license plate
void show(); // show content of garage floor
// by floor
};
Parkbox::Parkbox(char *s ) { // CTOR
license_plate = new char[strlen(s)+1];
strcpy(license_plate, s);
//cout << "ParkBox CTOR" << endl;
}
Parkbox::~Parkbox() { // DTOR
delete [] license_plate;
//cout << "ParkBox DTOR" << endl;
}
ParkingGarage::ParkingGarage(int row, int col, int flr){
rows = row; columns = col; floors = flr;
p2parkboxes = new Parkbox**[row];
for (int i = 0; i < row; ++i) {
p2parkboxes[i] = new Parkbox*[col];
for (int j = 0; j < col; ++j)
p2parkboxes[i][j] = new Parkbox[flr];
}
}
ParkingGarage::~ParkingGarage(){
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < columns; ++j)
delete [] p2parkboxes[i][j];
delete [] p2parkboxes[i];
}
delete [] p2parkboxes;
}
void ParkingGarage::show(){
int i,j,k;
for (i = 0 ; i < floors; i++){
cout << "Floor" << i << endl;
for (j=0;j<rows;j++){
for (k=0;k<columns;k++){
cout << p2parkboxes[j][k][i].get_plate() << " ";
}
cout << endl;
}
}
}
bool ParkingGarage::park_car(char*s){
p2parkboxes[0][0][0] = Parkbox(s); //test
//p2parkboxes[0][0][0] = s; //test
return true;
}
int main(void) {
// a parking garage with 2 rows, 3 columns and 4 floors
ParkingGarage pg1(2, 3, 4);
pg1.park_car("HH-AB 1234");
/*pg1.park_car("HH-CD 5678");
pg1.park_car("HH-EF 1010");
pg1.park_car("HH-GH 1235");
pg1.park_car("HH-IJ 5676");
pg1.park_car("HH-LM 1017");
pg1.park_car("HH-MN 1111"); */
pg1.show();
/*pg1.fetch_car("HH-CD 5678");
pg1.show();
pg1.fetch_car("HH-IJ 5676");
pg1.show();
pg1.park_car("HH-SK 1087");
pg1.show();
pg1.park_car("SE-AB 1000");
pg1.show();
pg1.park_car("PI-XY 9999");
pg1.show(); */
return 0;
}
You did not declare the copy constructor for the Parkbox class. So, the line
p2parboxes[0][0][0] = Parkbox(s)
creates something (instance of Parkbox with a char* pointer) on the stack (and deletes it almost immediately). To correct this you might define the
Parkbox& operator = Parkbox(const Parkbox& other)
{
license_plate = new char[strlen(other.get_plate())+1];
strcpy(license_plate, other.get_plate());
return *this;
}
Let's see the workflow for the
p2parboxes[0][0][0] = Parkbox(s)
line.
First, the constructor is called and an instance of Parkbox is created on stack (we will call this tmp_Parkbox).
Inside this constructor the license_plate is allocated and let's say it points to 0xDEADBEEF location.
The copying happens (this is obvious because this is the thing that is written in code) and the p2parboxes[0][0][0] now contains the exact copy of tmp_Parkbox.
The scope for tmp_Parkbox now ends and the destructor for tmp_Parkbox is called, where the tmp_Parkbox.license_plate (0xDEADBEEF ptr) is deallocated.
p2parboxes[0][0][0] still contains a "valid" instance of Parkbox and the p2parboxes[0][0][0].license_plate is still 0xDEADBEEF which leads to the undefined behaviour, if any allocation occurs before you call the
cout << p2parboxes[0][0][0].license_plate;
Bottom line: there is nothing wrong with the line itself, the problem is hidden within the implementation details of the '=' operator.
At this point it is really better for you to use the std::string for strings and not the razor-sharp, tricky and explicit C-style direct memory management mixed with the implicit C++ copy/construction semantics. The code would also be better if you use the std::vector for dynamic arrays.
The problem here is that you do not have deep copy assignment semantics. When you assign a temporary Parkbox to the Parkbox in the parking garage, the compiler generated assignment operator makes a shallow copy of the pointer license_plate, leaving both Parkboxes pointing at the same memory location. Then the temporary Parkbox goes out of scope and deletes license_plate. Since the other Parkbox is pointing at the same spot its license_plate gets deleted, too.
There are a couple solutions. One way to solve the problem is to define an assignment operator and a copy constructor that provide proper semantics, i.e. that perform deep copies of the license plate string. The better option, and the one that makes better use of C++, is to use std::strings instead of manually allocated C-strings. I strongly suggest the second approach, though working through the first might be instructive.
From the OP:
I solved the Problem with :
void Parkbox::change_plate(char *s){
delete [] license_plate;
license_plate = new char[strlen(s)+1];
strcpy(license_plate, s);
}