c++ pthreads and struct's corrupting data - c++

I'm new to pthreads and having a hard time creating a thread with a struct and keeping it's data intact while re-casting it from a void pointer.
I've spent days searching around trying to find a reason for this and haven't had much luck. Out of my two structures (using two different threads) one re-casts correctly in the thread, but for whatever reason, the second doesn't.
Structs:
struct Arguments {
List linkedList;
Node node;
Arguments(){}
Arguments (List *newList, Node *newNode){
linkedList = *newList;
pcb = *newPCB;
}
};
struct ClockControl {
int counter = 0;
pthread_mutex_t lock;
};
Threads:
void *schedule(void *args){
//Arguments *newArgs = static_cast<Arguments*>(args); <-- Tried this, doesn't work either.
arguments *newArgs = (arguments *) args;
List tempList = (newArgs ->linkedList); //DATA HERE IS CORRUPTED/WRONG
Node tempNode = (newArgs ->node); //DATA HERE IS CORRUPTED/WRONG
cout << "Flagged" << Lendl;
return NULL;
}
void *clockTime(void *clock){
//This thread works fine
clockControl *newClock = (clockControl*) clock;
int localVariable = 0;
localVariable = (newClock -> counter);
pthread_mutex_lock(&(newClock -> lock));
localVariable++;
newClock->counter = localVariable;
pthread_mutex_unlock(&(newClock -> lock));
return NULL;
}
Main:
int main(int argc, char** argv)
{
pthread_t threads[NUM_THREADS]; //Defined as 5
clockControl clock;
clock.counter = 0;
pthread_mutex_init(&clock.lock, NULL);
//Lists are initialized with variables.
List pendingList = initializeList();
List readyList = initializeList();
Arguments *args = new Arguments(&readyList, &pendingList.head->info);
while (clock.counter < 6000){
pthread_create(&threads[1], NULL, clockTime, (void*) &clock);
if (clock.counter == pendingList.head->info.timeCreated){
pthread_create(&threads[0], NULL, schedule, (void*) &args);
//INSPECTING args HERE HAS ACCURATE DATA
}
//Clean up threads
for (int i = 0; i < 2; i++){
pthread_join(threads[i],NULL);
}
}
}
Like I said, I've searched around and pretty much spinning my wheels at this point. I have a suspicion it might be that the memory is being freed or cleaned up prior to the thread getting executed, but I can't find a way around it.
Any help would be appreciated.

You are passing the address of the pointer to args to your schedule function. When you use &args, args is already an Arguments* so you are passing an Arguments**. To solve this you can simply pass args by itself to the function.
Also just so you know, reinterpret_cast<Arguments*> is probably more appropriate than static_cast in this circumstance.

These two lines of code should be swapped
localVariable = (newClock -> counter);
pthread_mutex_lock(&(newClock -> lock)); z
i.e.
pthread_mutex_lock(&(newClock -> lock));
localVariable = (newClock -> counter);
So that localVariable will be the right value when more that one thread is reading the counter and updating it

Related

'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.

std::map pass by reference Pointer to Object

I'm coding a plugin for XPLANE10 which gets a MSG from ROS.
My IDE is QTcreator 4.1.0 based QT 5.7.0 for Ubuntu 64 Bit. I would like to use C++11 Standards
My code explained
The main initializes ROS and creates a map -> container.
ROS spins in a loop till my GUI sends a MSG where my AirPlane should fly.
The MSG contains 3 floats(phi, theta, psi) where "phi" is the AirPlane ID, theta contains the ID for my ETA(Estimated Time of Arrival)
and psi contains the ID for my pose All of the IDs are saved in the ParameterServer(lookuptable).
So at the beginning i look up the activeAirplanes which returns a vector . I would like to store them in a map where the key is the AirCraft ID and the second param is an instance of the Object.
So i have initialized the for example(looked in container while debugging):
[0] first = 1 // Airplane ID1
[0] second = new CObject(freq)
[1] first = 2 // Airplane ID2
[1] second = new CObject(freq)
If i get a MSG from GUI
phi = 1
theta=2
psi=3
,
ROS will callback
MSG(....std::map<i32, CObject> &container)
// if phi is 1 so use the mapkey 1 and trigger the method do_stuff from CObject
do_stuff(phi, theta, psi,freq)
I would like to call the in a function from main
int getPlanes(std::map<i32,CObject>& container)
{
...
getActiveAirplanesFromServer(activePlanes);
}
First Question:
How do i pass the container to my callback?
Second Question:
How do i parallelize do_stuff() so my callback will return to main and i'm able to command more aircrafts while the others are calculated?
Third Question:
How would be the correct syntax for getPlanes to pass the container by reference so getPlanes() can edit it?
Fourth Question:
Is there a difference between
std::map<i32,CObject*> map
std::map<i32,CObject>* map
and
std::map<i32,CObject*>::iterator it=container->begin();
std::map<i32,CObject*>::iterator* it=container->begin();
If yes, what do i want ? #4Solved
// I have to edit stuff 'cause of some restrictions in my company.
#include "Header.h"
int main()
{
f64 freq = 10;
std::map<i32, CObject>* container;
std::map<i32,CObject>::iterator* it=container->begin();
// ROS
if(!ros::isInitialized())
{
int rosargc = 0;
char** rosargv = NULL;
ros::init(rosargc, rosargv, "MainNode");//), ros::init_options::AnonymousName);
}
else
{
printf("Ros has already been initialized.....\n");
}
ros::NodeHandle* mainNodeHandle=new ros::NodeHandle;
ros::AsyncSpinner spinner(2);
ParameterServer * ptrParam= new ParameterServer(mainNodeHandle);
ros::Subscriber airSub=mainNodeHandle->subscribe<own_msgs::ownStruct>("/MSG",
1000,
boost::bind(MSG,
_1,
freq,
container));
std::vector<i32> activePlanes;
i32 retVal=0;
retVal += ptrParam-> ParameterServer::getActiveAirplanesFromServer(activePlanes);
if (retVal == 0 && activePlanes.size()>0)
{
for (u32 j =0; j <activePlanes.size(); j++)
{
container->insert (std::pair<i32,CObject> (activePlanes[j] , new CObject(freq)));
}
}
while (ros::ok())
{
spinner.start(); //spinnt sehr viel :-)
ros::waitForShutdown ();
}
std::cout<<"ENDE"<<std::endl;
int retval = 1;
return retval;
}
void MSG(const own_msgs::ownStruct<std::allocator<void> >::ConstPtr &guiMSG,
f64 freq,
std::map<i32, CObject> &container)
{
if ((guiMSG->phi != 0) && (guiMSG->theta != 0) && (guiMSG->psi != 0))
{
std::string alpha = std::to_string(guiMSG->phi)+std::to_string(guiMSG->theta)+to_string(guiMSG->psi);
container.at(guiMSG->phi) -> do_stuff(guiMSG->phi,guiMSG->theta,guiMSG->psi, freq);
}
else
{
std::cout<<" Did not receive anything\n"<<endl;
}
}
void do_stuff(...)
{
//copy the IDs to private Member of this single Object
//setROS() for this single Object
//callback the current AC pose via ID from XPLANE
//callback the wished AC pose via ID from ParamServer
// do some calculations for optimum flight path
// publish the Route to XPlane
}
EDIT::
Problem is i get it to compile now and if debug it and set a breakpoint at :
void MSG(const own_msgs::ownStruct<std::allocator<void> >::ConstPtr &guiMSG,f64 freq,std::map<i32, CObject*> &container)
{
..
/*->*/ container.at(guiMSG->)...
}
The Container remains empty.
So i read some stuff about pointers and i saw my errors..
I confused * and &
if i want to pass the adress of a variable i have to write like
int main()
{
int a = 0;
AddTwo(&a)
cout<<a<<endl; // Output: 2
}
void AddTwo(int* a)
{
a+=2;
}

passing a std::list to in to a thread make the data invalidate

I wanted to pass a std::list pointer in to a thread and within that thread to do some processing with those objects . but when i debugged i saw the casting was ok but the data pointing to garbage .. i am posting my original code please explain
//this thread is reponsible for cleaning client objects which are no longer usable
unsigned int __stdcall ConnectionCleanerThread(void *pData)
{
std::list<ConnectionToClient *> * list = (std::list<ConnectionToClient *> * )pData;
std::list<ConnectionToClient *>::const_iterator curOb = list->begin();
ConnectionToClient * pCur = NULL;
while (true)
{
Sleep(5000);
puts("Cleaner is running..");
while (curOb != list->end())
{
pCur = (*curOb);
printf("curretly searching con IP %s \n",pCur->GetIP());
if ((*curOb)->IsThreadExited())
{
printf("The connection object for %s is removed \n",pCur->GetIP());
list->remove(pCur);
delete pCur;
}
curOb++;
}
}
}

How do I cycle through a linked list to reduce a value?

I have a class called SensorNode, which contains (among other things) a linked list of sensor objects. The node has a data member for the amount of battery power it has left, and the sensors each have a data member for how much power they draw. I have a function called processTimeClick that is supposed to go through the entire linked list of sensors in the node, and subtract the amount of power that they use from the battery that the node has left. Unfortunately I get an "Error, bad access code" and I don't know why. Here's the function I have, I was hoping someone could see where my logic is wrong.
void SensorNode::processTimeClick() {
if (batt == 0) {
}
else {
temp = mySensors;
do {
if (batt <=0) {
cout << "\nThis node has run out of battery\n";
func = 0;
break;
}
batt = (batt - (temp->SensEl->getPC()));
temp = temp->LLelement;
} while (temp->LLelement != NULL); //My code stops here and says "Thread 1:EXC_BAD_ACCESS (code=1, address=0x0)
}
}
to make it easier to understand:
temp and mySensors are both pointers (declared in the SensorNode class) of type "SensorBlock" (which is the linked list object). batt is a float data member in the SnesorNode class.
Here's the declaration for the SensorBlock class:
class SensorBlock {
friend class SensorNode;
SensorBlock * LLelement;
sensor * SensEl;
SensorBlock(sensor* senspoint);
};
SensorBlock::SensorBlock(sensor* senspoint) {
SensEl = senspoint;
LLelement = NULL;
}
Thanks for the help!
I think you want your loop to look more like this:
while (temp) {
if (batt <=0) {
cout << "\nThis node has run out of battery\n";
func = 0;
break;
}
batt = (batt - (temp->SensEl->getPC()));
temp = temp->LLelement;
}
This way, temp is checked to make sure it isn't null before you try to use it.
If you have a loop like this:
do {
// use temp
temp = temp->LLelement;
} while (temp->LLelement);
it is equivalent to
beginning_of_loop:
// use temp -- oops it might be null!
temp = temp->LLelement;
// temp might be null here
if (temp->LLelement) goto beginning_of_loop;
If you put the while at the top it is equivalent to this:
beginning_of_loop:
if (!temp) goto end_of_loop:
// use temp -- can't be null
temp = temp->LLelement;
// temp might be null here, but we aren't using it
goto beginning_of_loop;
end_of_loop:

Linked list sorting function in C++ doesn't stop properly

Many thanks in advance!
So, I've made attempts to make this function work. There are mistakes in the function but cannot catch them.
It seems to me, that I've missed the logic of sorting.
Could you point me 'where to go'?
/* node*/
typedef struct client {
int number; /* */
int balance;/* */
char lastName[20]; /* */
char firstName [20];/* */
char phone[11]; /* */
char email[20];
struct client *prev;/* */
struct client *next;
struct client *tmp; /* */
} Client;
Client *firstc,*currentc,*newc, *a, *b,*tmp; /*pointers*/
/* *"firstc' firstc element in list
*'currentc' current node
*'newc' new node
*'a' temporary pointer to Sort function
*'b' temporary pointer to Sort function
*'tmp' temporary pointer to Sort function
*/
int counter = 0;
int cnum = 0; /*cnum gives unique account numbers avoiding misentering*/
/*---Sort function------*/
void Sort()
{
/* */
int a = 0;/*variables to store balance*/
int b = 0;/*variables to store balance*/
if(firstc==NULL)
printf("Database is empty"); /*message*/
else
currentc = firstc;
currentc->prev = NULL;
tmp = NULL;
while((currentc=currentc->next)!= NULL)
{ /* 1) compare two nodes;
2) IF balance >*/
int a = currentc->balance;
int b = currentc->next->balance;/* debugger stopped here... */
if (a>b)
//if(currentc->balance >currentc->next->balance)
{ /*swap nodes*/
/*code using three pointers*/
tmp = currentc->next;
currentc->next->next = currentc->next;
currentc->next->next = tmp;
}
/*3)move along the list*/
else
currentc = currentc->next;
/*4) repeat to the end of list*/
}
currentc = firstc;
listAll();
return;
}
int b = currentc->next->balance;/* debugger stopped here... */
When currentc is pointing to the last item in the list currentc->next will be null. So currentc->next->balance is an access through a null pointer.
Also, practices like making assignments in conditions like while((currentc=currentc->next)!= NULL) will eventually come back to hurt you. In this case it seems you are skipping the first item in the list.
You probably meant:
if(firstc == NULL)
printf("Database is empty"); /*message*/
else
{ /* missing braces spotted by others */
currentc = firstc;
currentc->prev = NULL;
tmp = NULL;
for( ; currentc != NULL; currentc = currentc->next)
{
if(currentc->next == NUL)
/* nothing to compare */
break;
...
}
}
Furthermore the swapping code is swapping the wrong nodes:
tmp = currentc->next;
currentc->next->next = currentc->next;
currentc->next->next = tmp;
will almost (but not quite) swap the next node (b), with the one after it instead of with (a). You need to use the prev pointer (However since this looks like homework I had better not tell you exactly how to do it). Also, you are initialising prev but you need to keep it up to date in the loop. Actually, your 3 lines above are equivalent to:
tmp = currentc->next;
currentc->next->next = tmp;
so I think you meant something else.
the problem is when currentc is the last node, currectc->next is null, thus currentc->next->balance make it crash.
add some validation like
if (currentc->next == null)
and set b to a default/predefined value or put some logic whether you swap the nodes or not.