Memory management in C++? - c++

I'm developing a simple vehicle routing problem algorithm and I have a little problem with memory management. So I have following classes
In this one I store data of an Order
Order::Order(int id, int idLoc, double xCoord, double yCoord, double demand, int startTime, int endTime, int serviceTime) {
this->id = id;
this->idLoc = idLoc;
this->xCoord = xCoord;
this->yCoord = yCoord;
this->demand = demand;
this->startTime = startTime;
this->endTime = endTime;
this->serviceTime = serviceTime;
}
Order::~Order() {
// TODO Auto-generated destructor stub
}
In this one I store a list of Orders which represent a sequence of customers to serve during the distribution.
Route::Route(int idRoute,Vehicle *vehicleRoute) {
id = idRoute;
vehicle = vehicleRoute;
demandRoute = -1;
serviceTimeRoute =-1;
earliestTimeRoute =-1;
latestTimeRoute = -1;
serviceDistanceRoute = -1;
orders = new std::deque<Order>;
}
Route::Route(int idRoute, std::deque<Vehicle>::iterator vehicleIterator) {
id = idRoute;
vehicle = &(*vehicleIterator);
demandRoute = -1;
serviceTimeRoute =-1;
earliestTimeRoute =-1;
latestTimeRoute = -1;
serviceDistanceRoute = -1;
orders = new std::deque<Order>;
}
Route::~Route() {
std::cout << "Destroying Route " << id << std::endl;
delete orders;
std::cout << "Route Destroyed" << std::endl;
}
Finally, here I store a set of routes.
Solution::Solution() {
solution = new std::deque<Route>;
}
Solution::~Solution() {
std::cout << "Destroying Solution" << std::endl;
delete solution;
std::cout << "Solution Destroyed" << std::endl;
}
The problem is here:
readCustomers(&orderList, &depotList);
readVehicles(&vehicleList);
std::deque<Vehicle>::iterator it = vehicleList.getVehicleList()->begin();
int routeID = 0;
Route route (routeID, it);
solution.getSolution()->push_back(route); //Problem
So I read Orders and Vehicles then I create Route route which has no Orders associated yet and finally I add this route to a solution.
When I compile this code I got following output:
Route address: 0x7fff7351e110
Solution's route address: 0x1ab8270
Destroying Route 0
Route Destroyed
Destroying Solution
Destroying Route 0
Route Destroyed
Solution Destroyed
*** Error in `/home/.../': corrupted double-linked list: 0x0000000001ab5800 ***
Used valgrind to gather more information about this error, got folowing messages:
IVR [1]: Invalid read of size 8
IVF [1]: Invalid free()/delete/delete[]/realloc()
I guess I am releasing same chunk of memory twice. But I don't see where.
Can any one help me with this one.

Route objects get copied when used in a std::deque.
I see no Copy operator and you allocate the orders with new. When a Route is now copied, the pointer is copied too. So you have two objects pointing to the same object and freeing the same memory.
Why are you using new and delete here. Embed the std::deque directly as a member and avoid new/delete.
If you need new/delete:
Try to use smart pointers
Implement a copy constructor and copy operator.
If you decide to add it as a member you need to declare it in the class:
class Route ...
{
...
std::deque<Order> orders;
There is no need for new delete at all.

Related

C++ Strings In Class Becoming Empty after Construction

I'm creating a program where part of its job is to store class objects labeled Client() in a binary tree.
I create the object within a switch statement with
Client newClient = Client (first, last, iD);
transactionsTree.Insert(newClient);
The switch statement is in a loop that is reading data, so after this case is executed and the program continues, the strings within that class get set to empty "" strings. I found this out in stepping through debugging and as soon as that case block executes the strings change to empty. Any other data that gets put into that class remains but those strings will not. Even if I declare those string names in the Client.h file they are still empty after the switch case where it was created. The code where I create the newClient shown above is in a Transactions.cpp, the transactionsTree is a class object of BSTree.cpp, and there's also Client.cpp, all these classes share a connection but I'm assuming my problem has to do with how I'm inserting the objects into the binary tree.
Here is the code with the switch statement case:
case 'O': // open an account
{
string first = list.front();
list.pop();
string last = list.front();
list.pop();
stringstream getiD(list.front()); // transfer string to int
list.pop();
int iD = 0;
getiD >> iD; // transferring string to int
if (transactionsTree.Retrieve(iD)) // if Client is already in tree, prints error message
{
cout << "ERROR: Account " << iD << " is already open. Transaction refused." << endl;
}
else // else creates new Client
{
Client newClient = Client (first, last, iD);
transactionsTree.Insert(newClient);
}
break;
}
And here is my insert method for the binary tree:
void BSTree::Insert(Client &newClient)
{
if (isEmpty())
{
Node *newNode = new Node(newClient);
this->root = newNode;
}
else
add(this->root, newClient);
}
BSTree::Node* BSTree::add(Node *node, Client &newClient) // helper function for Insert()
{
if (node == nullptr)
{
Node *newNode = new Node(newClient);
return newNode;
}
if (newClient.clientID < node->pClient->clientID)
node->left = add(node->left, newClient);
else
node->right = add(node->right, newClient);
}
edit1: Upon further examination, none of the strings in the class that are declared in the header or constructor hold, although here are string vectors that hold. I also have an array of strings with the whole array declared in the header of Client.cpp but when I try and print out any strings from any Client object it only prints out an address.
edit2: I've isolated my problem to two areas, one where I try to access the Client within the tree using:
Client *ptrClient; // create pointer to access the Client once found
ptrClient = &transactionsTree.getClient(iD);
and two within my getClient method which is within my binary tree class:
Client& BSTree::getClient(int id) // returns a Client object from the tree to process() in Transactions.cpp
{
return getTheClient(this->root, id);
}
Client& BSTree::getTheClient(Node * node, int iD) // helper function for getClient that returns a Client object in the tree
{
// no need for the if condition of iD not being found because I check if the iD is in the tree before this function is executed
if (node->pClient->clientID == iD)
{
cout << node->pClient->firstName << " PRINTED HERE~~~~~~~~~~~~~" << endl;
return *node->pClient; // return client if found
}
if (iD < node->pClient->clientID)
return getTheClient(node->left, iD);
else
return getTheClient(node->right, iD);
}
Does this updated information help you help me solve my problem?
I solved my problem, it was with the two lines:
Client newClient = Client (first, last, iD);
transactionsTree.Insert(newClient);
I changed it to:
Client *newClient = new Client (first, last, iD);
transactionsTree.Insert(*newClient);
This mattered because I was creating a new object in the stack and not the heap.

'std::bad_alloc' when trying to delete priority_queue elements C++

When returning a ship to the port, speed becomes 0.0 and user inputs shield and fuel.
–If fuel is 0.0, the ship gets destroyed
–Ships still in the priority_queue take 10 shield damage and lose 15 fuel
–If shield or fuel become less than 0.0, the ship gets destroyed
Trying to implement these instructions for my final project. The ships are pointer types and they are in a priority queue named 'battlefield'. The ships also exist in a list of pointers called 'port'. I'm trying to destroy the ships that receive lethal damage but when I try to show them, the Qt program crashes and I get bad_alloc error. This is the last thing I have to do for my project :(
Important code blocks from various files:
I already tried to delete the ships from the port, also tried directly deleting them from the port but the priority_queue gets messed up.
class Civilization {
string name;
int x;
int y;
list<Villager> villagers;
list<Ship*> port;
priority_queue<Ship*, vector<Ship*>, Ship::comp> battle;
}
void Civilization::damageShips()
{
priority_queue<Ship*, vector<Ship*>, Ship::comp> copy = battle;
Ship *s = battle.top();
s->setSpeed(0.0);
while(!copy.empty()) {
Ship *s = copy.top();
s->setShield(s->getShield() - 10);
s->setFuel(s->getFuel() - 15);
copy.pop();
}
priority_queue<Ship*, vector<Ship*>, Ship::comp> temp;
while(!copy.empty()) {
Ship *s = copy.top();
string id = s->getId();
if (s->getShield() > 0 && s->getFuel() > 0) {
temp.push(s);
} else
deleteShip(id);
copy.pop();
}
battle = temp;
battle.pop();
}
void battlefielddisplay::setCivilization(Civilization *civilizaition)
{
size_t size = civilizaition->battlefieldSize();
ui->battlefield_table->setRowCount(int(size));
Civilization &c = *civilizaition;
priority_queue<Ship*, vector<Ship*>, Ship::comp> copy = c.getBattlefield();
int cnt = 0;
while(!copy.empty()) {
Ship *s = copy.top();
QString id = QString::fromStdString(s->getId());
QString fuel = QString::number(s->getFuel());
QString speed = QString::number(s->getSpeed());
QString shield = QString::number(s->getShield());
QString warriors = QString::number(s->size());
QTableWidgetItem *idItem = new QTableWidgetItem(id);
QTableWidgetItem *fuelItem = new QTableWidgetItem(fuel);
QTableWidgetItem *speedItem = new QTableWidgetItem(speed);
QTableWidgetItem *shieldItem = new QTableWidgetItem(shield);
QTableWidgetItem *warriorsItem = new QTableWidgetItem(warriors);
ui->battlefield_table->setItem(cnt, 0, idItem);
ui->battlefield_table->setItem(cnt, 1, fuelItem);
ui->battlefield_table->setItem(cnt, 2, speedItem);
ui->battlefield_table->setItem(cnt, 3, shieldItem);
ui->battlefield_table->setItem(cnt, 4, warriorsItem);
cnt++;
copy.pop();
}
}
void MainWindow::on_battle_remove_ship_clicked()
{
if (flag) {
Civilization* c = videogame.searchCivilization(ui->civilization_search_input->text().toStdString());
double shield = ui->shield_battle_remove->value();
double fuel = ui->fuel_battle_remove->value();
Ship *s = c->getBattleShip();
s->setSpeed(0.0);
s->setShield(shield);
s->setFuel(fuel);
c->damageShips();
qDebug() << "[✔]" << "Removed ship from battlefield";
} else
QMessageBox::information(this, "Error", "Civilization not found");
}
bool Civilization::deleteShip(string &id)
{
bool found = false;
for(size_t i(0); i < shipSize(); ++i) {
auto it = port.begin();
advance(it, i);
auto x = *it;
if (x->getId() == id) {
port.erase(it);
delete x;
--i;
found = true;
}
}
return found;
}
The main problem I see is that you delete the objects without removing the pointers from the container. You are iterating the same container multiple times and trying to access the deleted objects.
An additional problem is that you have multiple copies of the same queue so even removing the pointer from the main container may cause problems.
Try to reconsider the algorithm paying special attention to the life time of the objects. For example you may have a lazy deletion: instead of deleting just mark the objects as those that shall be deleted later. You may have a cleanup at the end of your function.

Do C++ vector and Gtkmm work together perfectly?. Segmentation fault when getting values of vector<string> from gtkmm on_click method

I am in middle of creating treeview for my project using gtkmm and C++.
What I want to do is to get variable properties from my order class. And I choose to use vector to store those properties so I get them easily by calling that method in the different class such as my main_window class. I can successfully get all values from other classes except main_window class showing segmentation fault.
To run my program:
1/ type "make" in terminal
2/ type "./mice" to run program
3/ click file->test. The program crashes
main_window.cpp class:
void Main_window::on_test_click() {
std::cout<< " On _test_clicked\n";
//auto add 1 order
controller.execute_cmd(99);
//THE LINE BELOW IS NOT WORKING IN ON_TEST_CLICK
std::vector<std::string> record = controller.order_to_strings(0);
}
auto_add method from emporium. cpp
void Emporium::auto_add() {
Order order0(1);
add_order(&order0);
std::vector<std::string> record = order_to_strings(0);
std::cout << "This is printing from emporium.cpp class" <<std::endl
<< "Id:" << record[0] <<"State: "<< record[1]<<"Price:"<< record[2]<< std::endl;
}
vector methods in emporium, order, controller classes.
std::vector<std::string> Controller::order_to_strings(int index) {
emporium.order_to_strings(index);
}
std::vector<std::string> Emporium::order_to_strings(int index) {
return orders[index]->to_strings();
}
std::vector<std::string> Order::to_strings(){
std::vector<std::string> order;
order.push_back(std::to_string(id_number));
order.push_back(state.to_string());
order.push_back(std::to_string(price));
return order;
}
Error:
*** Error in `./mice': free(): invalid pointer: 0x00007fa77a295000 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7fa77d63a7e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7fa77d64337a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7fa77d64753c]
./mice[0x406793]
./mice[0x4065cf]
./mice[0x40630a]
./mice[0x405eb7]
./mice(_ZNSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EED1Ev+0x35)[0x405b03]
......
This is my full version of my project. Test folder is my simplified version: https://github.com/dtn9797/MICE/tree/master/test
In the method auto_add(), Order object is created, which is destroyed in the end of auto_add() method. However in mean time pointer to this object is added to vector orders. This pointer point to invalid data in memory outside auto_add() method. Accessing data behind this pointer give crash.
void Emporium::auto_add() {
Order order0(1); //creating order0 local variable
add_order(&order0); //here pointer to something that will be destroyed soon is stored
std::vector<std::string> record = order_to_strings(0);
std::cout << "This is printing from emporium.cpp class" <<std::endl
<< "Id:" << record[0] <<"State: "<< record[1]<<"Price:"<< record[2]<< std::endl;
} //order0 local variable is destroyed here
void Emporium::add_order (Order* order) {
orders.push_back(order);
}
One of possible solution to prevent crash you can create Order object like this:
void Emporium::auto_add() {
add_order(new Order(1));
std::vector<std::string> record = order_to_strings(0);
std::cout << "This is printing from emporium.cpp class" <<std::endl
<< "Id:" << record[0] <<"State: "<< record[1]<<"Price:"<< record[2]<< std::endl;
}
But then for code correctness, remember to delete orders that are in std::vector<Order*> orders in the Emporium class destructor.

Accessing Iterator After Deletion Causes Crash

so I'm used to coding in C# and have just started using C++ again after a pretty substantial break. Essentially what I'm trying to do is to create a program that has lists of students with IDs, in courses.
I have this code that essentially prints out all available students in courses.
auto allCourses = WSUCourse::getAllCourses();
std::for_each(
allCourses.begin(),
allCourses.end(),
GetCoursePrinter());
The GetCoursePrinter() is called in this code in the constructor
struct GetCoursePrinter
{
void operator () (
MyCourse *coursePtr
)
{
std::cout << coursePtr->getIdentifier() <<
": " <<
coursePtr->getTitle() <<
std::endl;
}
};
My problem is after I delete an enrollment like so
MyEnrollment *enrollmentPtr = MyEnrollment::findEnrollment(
MyStudent::getStudentWithUniqueID(1000002),
MyCourse::getCourseWithIdentifier("CS 2800")
);
delete enrollmentPtr;
And then try to print it with GetCoursePrinter it crashes. I believe this is because it's trying to access something that doesn't exist. What I'm wondering is if there is a way to call something like this
if (allCourses.current() != null)
{
GetCoursePrinter();
}
else
{
//do nothing
}
when you call:
delete enrollmentPtr;
you need to remove this item in environment.

Member variables of a object get overridden when creating another object in the object

I have a memory issue with a class of mine. The issue occurs when I create an object in a member function of a class. It is about the class below. I removed the member functions because they aren’t necessary:
class User
{
private:
bool locked;
bool active;
std::vector<City> * userCitys;
UserData userData;
Credentials credentials;
The problem occurs when I call this function:
int User::addCity(CityData cityData)
{
lockUserObject(); //Everything is fine here
City cityToAdd; //When this object is created, the memory of userCitys will get overridden
cityToAdd.activate();
userCitys->push_back(cityToAdd);
int cityID = userCitys->size() - 1;
userCitys->at(cityID).editCityData(cityData);
unlockUserObject();
return cityID;
}
In the first place I created userCitys on the stack. For test purpose I placed it on the Heap. The address of userCitys get overridden by some data. I can’t find the problem. the City is just a basic class:
Part of the header:
class City
{
private:
bool active;
Supplies supplies;
std::vector<Building> buildings;
std::vector<Company> companies;
std::vector<Share> shares;
std::vector<Troop> troops;
CityData cityData;
Constructor:
City::City()
{
active = false;
}
How is it possible that userCitys get overridden? This all happens on a single Thread so that can’t be a problem. I tried a lot of thing, but I can’t get it to work. What is the best approach to find the problem?
Edit:
Lock function:
void User::lockUserObject()
{
for( int i = 0; locked ; i++)
{
crossSleep(Settings::userLockSleepInterval);
if( i >= Settings::userLockMaxTimes )
Error::addError("User lock is over userLockMaxTimes",2);
}
locked = true;
}
I call the code here (Test function):
City * addCity(User * user)
{
Location location;
location.x = 0;
location.y = 1;
CityData citydata;
citydata.location = location;
citydata.villagers = 0;
citydata.cityName = "test city";
int cityID = user->addCity(citydata); //addCity is called here
City * city = user->cityAction(cityID);;
if( city == NULL)
Error::addError("Could not create a city",2);
return city;
}
The add user (Test code):
User * addUser()
{
UserData test;
test.name = "testtest";
Credentials testc("testtest",3);
//Create object user
int userID = UserControle::addUser(test,testc);
User * user = UserControle::UserAction(userID);
if( user == NULL)
Error::addError("Could not create a user",2);
return user;
}
My test function:
void testCode()
{
User * user = addUser();
City * city = addCity(user);
}
This function in called in main:
int main()
{
testCode();
return 0;
}
Here are UserAction and addUser in UserControle:
int UserControle::addUser(UserData userdata, Credentials credentials)
{
int insertID = -1;
for( int i = 0; i < (int)UserControle::users.size(); i++)
{
if( !UserControle::users.at(i).isActive() )
{
insertID = i;
break;
}
}
User userToInsert(userdata,credentials);
if( insertID != -1 )
{
UserControle::users.insert( UserControle::users.begin() + insertID,userToInsert);
return insertID;
}
else
{
UserControle::users.push_back(userToInsert);
return UserControle::users.size() - 1;
}
}
User* UserControle::UserAction(int userID) //check all indexes if greater then 0!
{
if( (int)UserControle::users.size() <= userID )
{
Error::addError("UserAction is out of range",3);
return NULL;
}
if( !UserControle::users.at(userID).isActive())
{
Error::addError("UserAction, the user is not active.",3);
return NULL;
}
return &UserControle::users[userID];
}
There's a few things you could try:
Remove code until the fault goes away. In other words, distill a minimal example from your code. I guess you'll then see the error yourself, otherwise post that small example program here and others will.
Don't use raw pointers. The question with those is always who owns what they point to. Use smart pointers instead, e.g. unique_ptr (C++11) or auto_ptr (C++98) for exclusive ownership.
If you have pointer members like "userCities", you need to think about what happens when copying instances of that class (you already wrote a proper destructor, or?). So, either prevent copying (make copy-constructor and assignment operator private and without implementing it) or implement them in a way that the vectors are properly cloned and not shared between different instances.
Don't use C-style casts. If those are necessary to get anything through the compiler, the code is probably broken.