C++ Unrelated pointer changing after function call - c++

I'm working on using pointers to add objects to a queue and ran into a weird behavioral problem I can't quite figure out.
Each object that gets added to the queue has a 'next' pointer that links them all together and I have a 'start' and 'end' pointer to keep track where each end of the queue is.
The problem I have is that when I pass the end pointer and the object (which is stored in pArray by its processID), it also changes the start pointer -- even though I'm not passing it to the function.
// snippet from my main.cpp
RQCount = 0;
if (RQCount == 0)
{
RQStart = &pArray[processID];
RQStart -> next = &pArray[processID];
endRQ = &pArray[processID];
pArray[processID].setStatus("Ready");
CPUHolder = RQStart;
CPU = RQStart -> CPUBurst;
RQStart ->pStatus = "Executing";
}
else
{
*endRQ = FCFS(endRQ, &pArray[processID]);
pArray[processID].setStatus("Ready")
}
RQCount++;
FCSC Method:
PCB FCFS (PCB *endRQ, PCB *obj)
{
endRQ -> next = obj;
endRQ = obj;
return *endRQ;
};
I've narrowed it down to the function, and what really stumps me is that I move those two lines of code to my main, it runs and behaves just fine. It's when I add the function it doesn't. I think it has to do with how I'm dealing with the pointers and dereferencing, but I could use some help understanding this. Thanks!
EDIT:
To emphasize, I'm not having an issue with variables not changing in the function, as someone marked this a duplicate question for. The issue is after the function is called, it changes RQStart (which is not passed to the function).
If I don't use a function, RQStart stay the same, when I use the function, RQStart changes to a different object.

If you do
RQStart = &pArray[processID];
// ...
endRQ = &pArray[processID];
and then pass endRQ to the function, that will be the same as if you passed RQStart.
So when you change endRQ->next that will also change RQStart->next.
This is one reason for the standard containers to have end() point one past the last element, and not to the last element.

Related

what /can/ you return from a function .. and expect it to be alive at arrival?

Once again I got cought on expecting a function to return a proper value and then be disapointed .. getting odd behavior and misleading debug-information instead.
It's fairly well known, that you cannot return a local variable from a function and expect it to arrive as you would expect. Testing
int i=2;
int k=4;
return make_pair<int,int>(i*i,k*k);
Does indeed return something respectable. But using more elaborate objects than simple types seems to catch me every time.
So, is there any formality that I can use for discriminating on what can and what cannot be returned safely from a function?
----------- added on edit: ------------
Here is the example that does not work, taken brutally out of context.
Problem-context is a (to be GUI) tree of rectangles for the screen.
Class node inherits from a base (rectangle) containing 3 pointers to plain types (again, used to make values stick) .. the base uses new in constructor
pair<node,node> node_handler::split( vector<node>::iterator& this_node, double ratio, bool as_horizontal ){
//this_node becomes parents to the split-twins
this_node->my_ratio=ratio;
double firstW, firstH;
double secW, secH;
glm::dvec2 afirst, asecond;
if(as_horizontal ){
firstW = *this_node->plWidth*LETTER_PIXEL_WIDTH;
firstH = *this_node->plHeight*LINE_PIXEL_HEIGHT*ratio;
afirst = *this_node->pPoint;
secW = firstW;
secH = LINE_PIXEL_HEIGHT*(*this_node->plHeight)*(1.0d-ratio);
asecond= afirst+glm::dvec2(0.0d, firstH);
}
else{
firstW = ratio*(*this_node->plWidth)*LETTER_PIXEL_WIDTH;
firstH = *this_node->plHeight*LINE_PIXEL_HEIGHT;
afirst = *this_node->pPoint;
secW = (1.0d*ratio)*(*this_node->plWidth)*LETTER_PIXEL_WIDTH;
secH = firstH;
asecond= afirst+glm::dvec2(firstW,0.0d);
}
return make_pair<node,node>( node(afirst ,firstW, firstH) , node(asecond ,secW, secH) ) ;
}
Technically, you can return anything from a function.
Now when you return a pointer or a reference to something that is only local, then you have a problem.
Solutions:
Return copies (OK with copy elision anyway)
Return shared_ptr<>/unique-ptr<> for something that must not be copied.
Return only basic types and pass to the function a reference to an object that might be modified.
Do not create something in the function that needs to be manually destroyed layer (say, a pointer created with new).
It's dawning on me, that classes containing pointer-members reasonably has to have custom copy/assignment operators. I never got to grips with the "rho" variable referred to in the books I read at the time ... "right_hand_object" it must be! That's my epiphany. It was following the business of the constructors and your talk of copyable objects that squeezed this old rho-problem of mine.
I'm sorry for having spread my frustration on you.

Deleting and Reassigning a pointer from QList<Object *> to new Object using Iterator, is this right?

I have a QList and I'm trying to replace the objects in the list with new objects. The context is that I have a list of custom objects (the class name is "Conversation") to represent a list of group chats in a messaging platform. I use std::find_if to iterate through the list of pointers to find one with the right ID, and I want to take the pointer to that found object, deallocate it (delete?), and reassign that pointer to point at an object I generate with the "new" keyword. I think I'm doing this right but I'm not sure how to verify.
I tried a couple different iterations, ran into some issues where I realized I was using a const_iterator rather than just an iterator, so I couldn't modify any data. But I've fixed that and it seems like it's working, but I'm not positive.
Here's what I've got:
GroupChat *gc = new GroupChat(); // extends Conversation
// ...I update the member data here...
auto foundChat = std::find_if(conversations_.Conversations.begin2(),
conversations_.Conversations.end2(),
[this, gc](Conversation* o) { // my code to find the correct one...
}
if (foundChat != conversations_.Conversations.end()) {
auto c = (*foundChat);
delete c; // Is this right? Not positive...
//*foundChat = nullptr; // do I need this?
c = gc;
}
It seems like it's working but I'm worried about dangling pointers and incorrect memory deallocation/allocation. Could someone spot check me on this? Thanks for any help!

Prevent v8::Local value from being garbage collected

I have a function that stores the value of an argument to an std::vector<v8::Local<v8::Value>> property of a C++ class exposes as an ObjectWrap like this:
NAN_METHOD(MyObject::Write) {
MyObject* obj = Nan::ObjectWrap::Unwrap<MyObject>(info.This());
obj->data.push_back(info[0]);
}
However, when I try to read back the value from another C++ function, the value is lost, and becomes undefined.
I'm passing a number to MyObject::Write, and I can confirm info[0]->IsNumber() returns true before pushing it to the vector, however when reading it back, the value it not a number, and in fact returns false for all the types I tested using Is<Type> methods from v8::Value, but still returns true for BooleanValue().
My guess is that the variable is being garbage collected after MyObject::Write returns, however I have no idea how to prevent this from happening.
I'm currently trying to initialise the value as a Persistent value. I tried the following attempts without success:
Nan::CopyablePersistentTraits<v8::Value>::CopyablePersistent p;
Nan::Persistent<v8::Value> persistent(info[0]);
Nan::CopyablePersistentTraits::Copy(persistent, p);
And:
v8::Isolate *isolate = info.GetIsolate();
v8::Persistent<v8::Value, v8::CopyablePersistentTraits<v8::Value>> persistent(isolate, info[0]);
But getting tons of C++ errors.
I was running into problems untangling this mess myself. There's a lot of template stuff going on here that we both missed. Here was the solution I found most readable:
// Define the copyable persistent
v8::CopyablePersistentTraits<v8::Value>::CopyablePersistent p;
// Create the local value
auto val = v8::Local<v8::Value>::New(
v8::Isolate::GetCurrent(), //< Isolate required
v8::Integer::New(v8::Isolate::GetCurrent(), v) //< Isolate required
);
// Reset() is a TEMPLATE FUNCTION, you have to template it with the same
// template type parameter as the v8::Local you are passing
p.Reset<v8::Value>(v8::Isolate::GetCurrent(), val); //< Isolate required
By "info" I assume you are referring to a v8::FunctionCallbackInfo reference. If so the above code would collapse to the following:
void SomeFunc(v8::FunctionCallbackInfo<v8::Value>& info) {
v8::CopyablePersistentTraits<v8::Value>::CopyablePersistent p;
p.Reset<v8::Value>(info[0]);
}
Because the persistent is now copyable you can do things like store it inside a standard library container. This was my use case. This is an example of storing a value in a vector:
std::vector<v8::CopyablePersistentTraits<v8::Value>::CopyablePersistent> vect;
void AccumulateData(v8::FunctionCallbackInfo<v8::Value>& info) {
v8::CopyablePersistentTraits<v8::Value>::CopyablePersistent p;
p.Reset<v8::Value>(info[0]);
vect.push_back(p);
}
I hope this helps someone out there.
If you plan on storing v8 values in C++, you need to make them persistent instead of local so they're independent of handle scope and not garbage-collected when the handle scope is released.
Nan has version-independant wrappers for v8::Persistent and Co. Because of using inside std::vector<>, you'll also need to initialize Nan::Persistent with Nan::CopyablePersistentTraits so it becomes copyable (or make an own reference-counted container for it).

Creating a vector in a method and setting it to a variable

OK so I an new to C++ and am fairly sure this should be a simple question if I can ask it right. Basically this is what I need to work:
printInfoFromVector(this->mycontroller.createVector)
This is the actual code I have:
vector<GasStation>& highPrices = this->myController.findHighestPrice();
this->findPrice(highPrices);
vector<GasStation>& findHighestPrice(){
The problem that I am having is that I can not get they types of highPrices and findHighestPrice() to match. Im fairly sure the problem is because I am passing by ref but I pretty sure that the right way to do it.
Can anyone tell me the correct way to write the assignment statement and the method head so that the types match?
If findHighestPrice is computing a new vector, then you should not return a reference, but an actual vector. Thus you would have:
vector<GasStation> findHighestPrice() { ... }
vector<GasStation> highPrices = this->myController.findHighestPrice();
For example, if you defined findHighestPrice as
vector<GasStation>& findHighestPrice() {
vector<GasStation> stations;
// ...
return stations;
}
then stations will be deallocated when the function returns and highPrices will be undefined.

C++ Linked List Error: lvalue required as left operand of assignment

Alright, I'm trying to write a program in C++ that deals with a double-linked list. Specifically, the list contains a collection of artwork objects as its nodes. In this particular function, I'm trying to remove nodes through the "sell" command, but I'm getting this error on several lines:
Error: lvalue required as left operand of assignment
I've done my research and I've found that this type of error commonly arises when you try to assign values when you actually want to compare them, or if you're trying to assign values to a constant. However, I don't think that's my problem. Here's the problem code:
// Sell At Function: This function sells the specified artwork.
void CR_ArtCollection::sell_at(string title, ostream& log)
{
CR_ArtWorks* walker = first;
while(walker != NULL)
{
if(title == walker->get_title())
{
walker->get_next()->get_prev() = walker->get_prev(); // Error
walker->get_prev()->get_next() = walker->get_next(); // Error
delete walker;
walker = NULL;
}
else walker = walker->get_next();
}
}
If anyone can point me in the right direction, I would be incredibly appreciative.
It's quite obvious - get_prev and get_next return r-values. That means you can't assign to them.
Check your interface for a method similar to set_next and set_prev and call it as:
walker->get_next()->set_prev(walker->get_prev());
walker->get_prev()->set_next(walker->get_next());
As the names suggest - get_xxxx, those methods are there so you can get the values, not also set them.
Alright, if a function returns a primitive type such as a integer or a pointer it is not legal to assign to the result of the function. That's the error you have.
One possibility would be to change your get_prev and get_next function to return references to pointers.
But I don't suggest you do that. Your code clearly needs redesigning. You should add an erase function to your linked list class. That way the pointer manipulation code will be in the CR_ArtWorks class where it belongs, instead of the CR_ArtCollection class where it doesn't.