Accessing Iterator After Deletion Causes Crash - c++

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.

Related

C++ std::set<std::wstring> strange behavior?

I'm writing a party system for a game, and I'm getting some very strange behavior out of a std::set std::wstring that contains IP addresses for the party. The error I'm getting is in xtree, usually in clear, but I've also hit it in insert. It's a read access violation at _Head->_Parent, usually says something like "_Head->_Parent was [memory address]."
This problem is very rare, and I've been trying to reproduce it for 2 months with no success. The game is up 24/7, and thousands of parties are created and destroyed each day, and I only get this error 2-3 times a week. Everything that inserts into, erases from, iterates over, or clears this set has a global mutex around it, that's only used for this set. Here's the relevant code:
Party.h
```
private:
std::set<std::wstring> ipList;
public:
std::set<std::wstring> getIPList() { return ipList; }
```
Party.cpp
```
PartyManager::DisbandParty(Party* party){
SAFE_DELETE(party);
}
Party::~Party(){
ipList.clear();
}
Party::AddPartyMember(){
getUniquePlayerLock.lock();
ipList.insert(s2ws(player->GetClientSession()->GetRemoteIP()));
getUniquePlayerLock.unlock();
}
Party::LeaveParty(){
getUniquePlayerLock.lock();
ipList.erase(s2ws(player->GetClientSession()->GetRemoteIP()));
getUniquePlayerLock.unlock();
}
Party::KickMember(){
getUniquePlayerLock.lock();
ipList.erase(s2ws(kickedplayer->GetClientSession()->GetRemoteIP()));
getUniquePlayerLock.unlock();
}
Party::GetUniquePlayers(){
std::set<std::wstring>::iterator it;
std::wstring curIP;
std::list<CPlayer*> uniquePlayers;
if (!ipList.empty()) {
for (it = ipList.begin(); it != ipList.end(); it++)
{
curIP = *it;
//std::wcout << "\nChecking IP " << curIP;
for (int i = 0; i < m_byMemberInfoCount; i++)
{
//std::cout << "\n" << i;
CPlayer* player = GetPlayer(i);
if (player) {
if (curIP == s2ws(player->GetClientSession()->GetRemoteIP())) {
uniquePlayers.push_back(player);
//std::wcout << "\n" << curIP;
break;
}
}
}
}
}
return uniquePlayers;
}
```
I'm all out of ideas here. It has to be some sort of undefined behavior, memory corruption, or something very obvious that I'm missing. Maybe in certain circumstances ipList is being destroyed before the party destructor is called? I'm still fuzzy on when variables declared in header files are considered "out of scope" and thus destroyed. Any help is appreciated.
Edit: With this logic, would the value of player->GetClientSession()->GetRemoteIP() be destroyed until it is repopulated?
Edit2: I've made some changes to check for nulls in the client session and IP as requested. This time, I'm getting an access violation error on accessing the lower bound of the set.
```
template <class _Keyty>
_Tree_find_result<_Nodeptr> _Find_lower_bound(const _Keyty& _Keyval) const {
const auto _Scary = _Get_scary();
_Tree_find_result<_Nodeptr> _Result{{_Scary->_Myhead->_Parent, _Tree_child::_Right}, _Scary->_Myhead}; **ACCESS VIOLATION ERROR IS HERE**
_Nodeptr _Trynode = _Result._Location._Parent;
while (!_Trynode->_Isnil) {`enter code here`
_Result._Location._Parent = _Trynode;
if (_DEBUG_LT_PRED(_Getcomp(), _Traits::_Kfn(_Trynode->_Myval), _Keyval)) {
_Result._Location._Child = _Tree_child::_Right;
_Trynode = _Trynode->_Right;
} else {
_Result._Location._Child = _Tree_child::_Left;
_Result._Bound = _Trynode;
_Trynode = _Trynode->_Left;
}
}
return _Result;
}
```
What could I possibly be doing to this set to cause this memory access error? It's a member variable being accessed in a class function, with no out of band destructors being called on it anywhere. I'm totally lost here.
Edit 3: Adding ifdefs for the global mutex below:
globalVariables.h:
#pragma once
#ifndef playerLockDefined
#include <mutex>
#define playerLockDefined
extern std::mutex getUniquePlayerLock;
#endif // !1
globalVariables.cpp:
#include "stdafx.h"
#include "globalVariables.h"
std::mutex getUniquePlayerLock;

boost::stacktrace::frame::name() hangs

I am trying to retrieve a stack trace in my program, and store it for later use (debugging purposes). But the call to boost::stacktrace::frame::name() never returns, and I have no clue why. When I use this exact code in a simple project, it runs nicely. Any ideas?
boost::stacktrace::stacktrace stacktrace;
stringstream stacktraceText;
for (const auto& entry : stacktrace)
{
if (entry.empty() == false)
{
auto name = entry.name();
stacktraceText << name << "\n";
}
else
{
stacktraceText += L"<missing symbol info>\n";
}
}

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.

How can I write a file with containing a lua table using sol2

I've settled on using lua as my config management for my programs after seeing posts like this and loving the syntax, and sol2 recently got released so I'm using that.
So my question is, how can I grab all the variables in my lua state and spit them out in a file?
say,
sol::state lua;
lua["foo"]["bar"] = 2;
lua["foo"]["foobar"] = lua.create_table();
would, in turn, eventually spit out
foo = {
bar = 2
foobar = {}
}
Is this at all possible and if so, how?
I used this serializer to serialize my table and print it out, really quite easy!
This is what I came up with
std::string save_table(const std::string& table_name, sol::state& lua)
{
auto table = lua["serpent"];
if (!table.valid()) {
throw std::runtime_error("Serpent not loaded!");
}
if (!lua[table_name].valid()) {
throw std::runtime_error(table_name + " doesn't exist!");
}
std::stringstream out;
out << table_name << " = ";
sol::function block = table["block"];
std::string cont = block(lua[table_name]);
out << cont;
return std::move(out.str());
}

Memory management in 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.