i asked a similar question here yesterday and i corrected some of the issues but the main one still persists.
Im enqueuing and dequeueing Position objects into a Position queue.As i enqueue 2 different Position objects, and dequeue both back out, both Position objects that are returned have the same value as the 2nd object put in. When i check the values that have been enqueued inside the enqueue function they are correct.I dont understand how this wont work as ive worked out the logic and used the dequeue algorithm verbatim from a book;
The Position class has 3 array based stacks as private members
struct Posnode
{
Position *pos;
Posnode *next;
};
class Position
{
private:
Posnode *front,*back,header; //front = back = &header;
Pegs A,B,C;
Position::Position(int num): A(num), B(num), C(num)
{
front = back = &header;
A.assignpeg(num);//assigning 1 to n to each Peg
B.assignpeg(num);
C.assignpeg(num);
}
#include "Pegs.h"
#include "Position.h"
int main ()
{
Position pos(4), intial(3),p,m,n;
intial.geta();//poping Peg A stack
pos.getc();//poping Peg c stack
p.enqueue(intial);
p.enqueue(pos);
p.dequeue(m);//position 'pos' is returned rather than intial
p.dequeue(n);//position 'pos' is returned
cin.get();
return 0;
}
void Position::dequeue(Position&)
{
Position p;
Posnode *ptr=front->next;//front points to an empty node wi
p = *ptr->pos;//assigning the position in ptr to p
front->next = ptr->next;
if (back == ptr) {//if im at the end of the queue
back = front;
}
delete ptr;
return ;
}
void Position::enqueue(Position n)
{
Posnode *ptr = new Posnode;
ptr-> pos = &n;//copying Position n calls Pegs operator =
back->next = ptr;//values that are enqueued check back ok
back = ptr;
return;
}
Pegs& Pegs::operator=(const Pegs & ori)//Pegs copy contructor
{
top=-1;
disks = ori.disks;
peg = new int[disks];
int element=0,g=-1,count=0;
while (count <= ori.top)//copying elements if there are any in ori
{
++count;
element=ori.peg[++g];
push(element);
}
return *this;
}
Sorry mate, but there are many problems with your code. Some of them seem to be copy/paste errors, but other show lack of C++ understanding. I'll focus on the latter first.
The member function void Position::enqueue(Position n) copies all passed arguments by value. So what happens when you call it? The parameter is copied and inside the function you are dealing with this copy that will be disposed when the function's scope ends. So assignemtn ptr-> pos = &n will assign an address of a temporary object to pos. Data at the address of disposed object may still be valid for some time, as long as nothing writes over it, but you should never ever depend on this behaviour. What you should do is you should pass the parameter by reference, i.e. change the declaration to void Position::enqueue(Position& n). That way the actual object will be passed, not a automatic copy.
If you don't specify a name for an argument like in void Position::dequeue(Position&), you won't have access to it. Inside this function you create a local variable p and then assign the result to it. But because p is local it will be disposed when the function returns. Needless to say, the parameter that you pass to this function is inaccessible because it's unnamed. What you should do is you should declare the function like that: void Position::dequeue(Position& p).
As a good advice: you should do better job with isolating your case. For example, are Pegs connected in any way to the problems you are having? Also avoid declarations like Posnode *front,*back,header - in most cases they make code harder to read. And did you notice that your code has #includes inside class body?! You should never to that, except for times when you exactly know what you are doing. #include directives should be usually put in the first lines of a source file.
Related
I am new to CPP and I am writing a program as an assignment to simulate a train path system that includes destinations and starts using object oriented programming .
I have 2 classes as shown below (there is a a passenger class but it is not relevant ) :
class Train
{
public:
int cooldown_time;
int travel_time;
int time_since_movement;
int id;
class Station *start;
class Station *destination;
vector<Passenger *> current_passengers;
string status;
void add_train(vector<string> commands, vector<Station> stations, vector<Train> &trains)
{
travel_time = stoi(commands[THIRD_PART + 1]);
cooldown_time = stoi(commands[THIRD_PART + 2]);
status = TSTATUS1;
start = station_search(stations, commands[SECOND_PART]); // this is where the problem happens
destination = station_search(stations, commands[THIRD_PART]);
id = stations.size();
}
};
class Station
{
public:
int tuffy_price;
string city_name;
vector<Passenger *> current_passengers;
vector<Train *> current_trains;
int id;
void add_station(vector<Station> &stations, vector<string> &commands)
{
tuffy_price = stoi(commands[THIRD_PART]);
city_name = commands[SECOND_PART];
id = stations.size();
}
};
I have a search function dedicated to finding the start and destination based off a command that user enters for example :the user enters "add_train cityname1 cityname2 <cooldown_time> <travel_time>". my program detects the city names and searches a vector I have named stations with a key that is the city name and returns a pointer (because of the complications in memory behavior in a function , i set it to pointer) to that station-object .
the function is as below :
Station *station_search(vector<Station> stations, string key)
{
Station *dummy;
for (int i = 0; i < stations.size(); i++)
{
if (stations[i].city_name == key)
{
return &stations[i];
}
}
return dummy;
}}
my problem is with my search function's weird behavior , when I debug the program I see the function find the correct station object and return a pointer to it ,but when the execution returns to the constructor function it randomly (maybe not randomly ) turns the first pointer relating to the start station to null and replaces the values inside with garbage ones.
but after the function searches for the destination station it does not do this and the execution is correct.
Could someone explain why this error is occurring?
My guess is that I have not understood local variables and pointer returns well enough and I have committed a rookie mistake somewhere but I don't seem to find it .
PS: I did not include the full code as it's too long I can include it by attaching a file ,comment down if it's necessary.
Station *station_search(vector<Station> stations, string key)
If you take a closer look here, you will see that the stations parameter is passed by value, which means that after this function returns, this stations parameters will get destroyed. It will be no more. It will cease to exist. It will become an ex-parameter.
However this station_search returns a pointer to some value in this vector. Therefore, rules of logic dictate that it will return a pointer to a destroyed object. Attempting to dereference that pointer, in any way, becomes undefined behavior.
Your other class methods receive parameters by reference, so you must already understand the difference between passing parameters by value vs. by reference, so you should simply do the same here.
Here you are passing a copy of the vector, which is destroyed when the function returns. Additionally, if the key is not found an uninitialized pointer is returned.
Station *station_search(vector<Station> stations, string key)
{
for (Station &station : stations)
{
if (stations.city_name == key)
{
// Pointer becomes invalid when you leave.
// Accessing this pointer will cause undefined behavior.
return &station;
}
}
// This would always cause undefined behavior as dummy was not initialized.
return nullptr;
}
You should pass in a reference and initialize dummy:
Station *station_search(vector<Station> &stations, string key)
I am not experienced enough in C/C++ programming, so I am asking for an explanation.
I have global array declared as following. ASAK it is located in seperate memory part of initialized global memory in context of process memory.
Sensor sensorsArray[SENSORS_COUNT] = {dhtTempSensor, dhtHumSensor, dallasTempSensor, waterLevelSensor};
I need to find element in this array and return pointer to it (because I am going to change its value). I have written such function.
Sensor* getSensorById(uint32_t id) {
for (int i = 0; i < SENSORS_COUNT; i++) {
Sensor* current = &sensorsArray[i];
if (current->sensorId == id) {
return current;
}
}
}
Will it work properly, I am not sure about current pointer, it is allocated on the stack so it is in function scope, will it be poped from the stack after function ends ? Or it will work properly.
I mean not pointer(address of array element which is taken using &sensorsArray[i]), but current pointer variable which contains address of erray element, will it be poped or not.
Please suggest best way how to do in such situation.
Thx.
You aren't covering all the possible returning cases of the function, namely, the case when the id does not match with any of the ids of the array.
Currently the pointer will return the last element of the array if there is no match.
You could correct that by defining the pointer Sensor* sensor_found = nullptr outside the for loop such that if there is no sensor found the return value is still valid, i.e. nullptr and assigning the found value of current to sensor_found, only if there is a match.
Sensor* getSensorById(uint32_t id) {
Sensor* sensor_found = nullptr;
for (int i = 0; i < SENSORS_COUNT; i++) {
Sensor* current = &sensorsArray[i];
if (current->sensorId == id) {
sensor_found = current;
break;
}
}
return sensor_found;
}
If the id found return current, otherwise, if there is no match return nullptr.
you want to make sure that the function has a valid return statement on its every execution path. In you current implementation if the id is not matched then the return value of Sensor* is not set and will contain random bytes. One wau to deal with this situation is to return the nullptr to indicate that the Sensor was not found. Other than that, ythe function will work properly.
Sensor* getSensorById(uint32_t id) {
for (int i = 0; i < SENSORS_COUNT; i++) {
Sensor* current = &sensorsArray[i];
if (current->sensorId == id) {
return current;
}
}
return nullptr; // id not matched
}
Your code is fine (as the comments suggest). The reason why you don't need to worry about the current pointer becoming invalid is because the memory that it points to (ie, the global array) stays valid beyond the scope of the function. Just because you happen to create a pointer (and remember, a pointer is really just a number that corresponds to some place in memory) to that memory doesn't mean that it becomes invalid when used elsewhere.
When you say Sensor *current = &sensorArray[i];, then if sensorArray[i] is stored at, say, position 0x10 in memory, then current = 0x10, and no matter where it is used, then sensorArray[i] will still be at memory location 0x10. When you assign a value to current, you are not copying the value from the sensor, you are merely getting a pointer to it.
When I push a pointer of struct into a std::queue, and then poping the value, the value that I'm getting back would change to zero. I've simplified the actual code to illustrate the problem below. The head pointer in the real code is a class variable and contains other values. If I push head onto the queue, all other values that I get also become uninitialized.
What could be the issue here?
Note: PipePixel *head; is an instance variable declared in the class header file.
Add Head Function:
void LinkedGraph::addHeadPixel(int index) {
PipePixel pixel = {NULL, 433, std::vector<PipePixel*>()};
pixel.index = index;
if (head==NULL) {
pixelMap[index] = &pixel;
head = &pixel;
} else {
printf("Already added head pixel! Px:%d\n", pixelMap[index]->index);
}
}
Print Function: <-- Where problem occurs
std::queue<PipePixel*> printQueue;
printQueue.push(head);
printf("headIndex:%d\n", head->index); // headIndex:433
while (!printQueue.empty()) {
PipePixel *child = printQueue.front();
printf("childIndex:%d\n", child->index); //childIndex:0
printQueue.pop();
if (child == NULL) {
printf("child is null"); // no output
continue;
}
}
PipePixel Struct:
struct PipePixel {
PipePixel *parent;
int index; //pixel index
std::vector<PipePixel*> children;
};
The problem here is that the variable pixel is local inside the LinkedGraph::addHeadPixel function. Once the function returns that object is destructed and the variable ceases to exist. If you have stored a pointer to a local variable, that pointer no longer points to a valid object, and dereferencing the pointer leads to undefined behavior.
My recommendation is to not use pointers at all, but let the compiler handle he object copying. For such small and simple objects its possible performance impact is negligible.
now i have been making games for a few years using the gm:s engine(tho i assure you i aint some newbie who uses drag and drop, as is all to often the case), and i have decided to start to learn to use c++ on its own, you know expand my knowledge and all that good stuff =D
while doing this, i have been attempting to make a list class as a practice project, you know, have a set of nodes linked together, then loop threw those nodes to get a value at a index, well here is my code, and i ask as the code has a single major issue that i struggle to understand
template<class type>
class ListNode
{
public:
type content;
ListNode<type>* next;
ListNode<type>* prev;
ListNode(type content) : content(content), next(NULL), prev(NULL) {}
protected:
private:
};
template<class type>
class List
{
public:
List() : SIZE(0), start(NULL), last(NULL) {}
unsigned int Add(type value)
{
if (this->SIZE == 0)
{
ListNode<type> a(value);
this->start = &a;
this->last = &a;
}
else
{
ListNode<type> a(value);
this->last->next = &a;
a.prev = this->last;
this->last = &a;
}
this->SIZE++;
return (this->SIZE - 1);
}
type Find(unsigned int pos)
{
ListNode<type>* a = this->start;
for(unsigned int i = 0; i<this->SIZE; i++)
{
if (i < pos)
{
a = a->next;
continue;
}
else
{
return (*a).content;
}
continue;
}
}
protected:
private:
unsigned int SIZE;
ListNode<type>* start;
ListNode<type>* last;
};
regardless, to me at least, this code looks fine, and it works in that i am able to create a new list without crashing, as well as being able to add elements to this list with it returning the proper index of those elements from within the list, however, beyond that the problem arises when getting the value of a element from the list itself, as when i ran the following test code, it didn't give me what it was built to give me
List<int> a;
unsigned int b = a.Add(313);
unsigned int c = a.Add(433);
print<unsigned int>(b);
print<int>(a.Find(b));
print<unsigned int>(c);
print<int>(a.Find(c));
now this code i expected to give me
0
313
1
433
as that's what is been told to do, however, it only half does this, giving me
0
2686684
1
2686584
now, this i am at a lost, i assume that the values provided are some kind of pointer address, but i simply don't understand what those are meant to be for, or what is causing the value to become that, or why
hence i ask the internet, wtf is causing these values to be given, as i am quite confused at this point
my apologies if that was a tad long and rambling, i tend to write such things often =D
thanks =D
You have lots of undefined behaviors in your code, when you store pointers to local variables and later dereference those pointers. Local variables are destructed once the scope they were declared in ends.
Example:
if (this->SIZE == 0)
{
ListNode<type> a(value);
this->start = &a;
this->last = &a;
}
Once the closing brace is reached the scope of the if body ends, and the variable a is destructed. The pointer to this variable is now a so called stray pointer and using it in any way will lead to undefined behavior.
The solution is to allocate the objects dynamically using new:
auto* a = new ListNode<type>(value);
Or if you don't have a C++11 capable compiler
ListNode<type>* a = new ListNode<type>(value);
First suggestion: use valgrind or a similar memory checker to execute this program. You will probably find there are many memory errors caused by dereferencing stack pointers that are out of scope.
Second suggestion: learn about the difference between objects on the stack and objects on the heap. (Hint: you want to use heap objects here.)
Third suggestion: learn about the concept of "ownership" of pointers. Usually you want to be very clear which pointer variable should be used to delete an object. The best way to do this is to use the std::unique_ptr smart pointer. For example, you could decide that each ListNode is owned by its predecessor:
std::unique_ptr<ListNode<type>> next;
ListNode<type>* prev;
and that the List container owns the head node of the list
std::unique_ptr<ListNode<type>> start;
ListNode<type>* last;
This way the compiler will do a lot of your work for you at compile-time, and you wont have to depend so much on using valgrind at runtime.
I'm trying to implement the Ford Fulkerson Algorithm in C++.
However, I'm having trouble with my find_edge function. When I call this function in my_alg, it chooses the correct edge and then the flow is incremented in my_alg. It chooses the right edge and increment its flow (flow), but when I call the find_edge function again, the flow is not incremented as it should be.
This results in an endless loop of my algorithm. Probably I do something wrong with the pointers. You can see my code below.
//An object of this class represents an edge in the graph.
class Edge
{
private:
//Node *prev;
public:
int flow;
Edge(Node *firstNode, Node *secNode, unsigned inCost) {
orgNode = firstNode;
dstNode = secNode;
bridge_capacity = inCost;
}
Edge() {
flow=0;
}
};
//An object of this class holds a vertex of the graph
class Node
{
public:
Node *prev;
vector<Edge>& getAdjNodeList() {
return adjNodeList;
}
};
Edge *find_edge(Graph *g,Node *from,Node *to) {
vector<Edge> b=from->getAdjNodeList();
for(int i=0;i<b.size();i++) {
if(b[i].getDstNode()==to)
return (&b[i]);
}
return NULL;
}
int my_alg(Graph *as,Node *source,Node *sink){
Edge *find_edge();
int max_flow=0;
while(bfs(as,source,sink)) {
Node *b=as->nodeList[num_isl];
int inc=100000000;
while(b->prev!=NULL) {
Edge *bok=find_edge(as,b->prev,b);
inc=min(inc,bok->get_bridge_capacity()-bok->flow);
b=b->prev;
}
b=as->nodeList[num_isl];
while(b->prev!=NULL){
Edge *bok = find_edge(as,b->prev,b);
bok->flow += inc; // This is the place the flow is incremented
bout << bok->flow; // Here, everything is alright.
bok = find_edge(as,b->prev,b);
cout << bok->flow; // However, this is is not the correct result.
}
max_flow+=inc;
}
return max_flow;
}
I had a more thorough look at your code. To help you track your problems down yourself in the future, I will show you a sample process of finding the error.
If you really can not find the problem by looking at the code, you may want to strip down everything that obfuscates your view on the problem. The reduced code could look like this:
class Edge {
public:
int flow;
};
class Node {
private:
vector<Edge> adjNodeList; // list of outgoing edges for this vertex
public:
vector<Edge> & getAdjNodeList() {
return adjNodeList;
}
void addAdjNode(Node* newAdj) {
adjNodeList.push_back(Edge(newAdj));
}
};
int main() {
Node *node1 = new Node();
Node *node2 = new Node();
node1->addAdjNode(node2);
vector<Edge> t = node1->getAdjNodeList();
vector<Edge> f = node1->getAdjNodeList();
t[0].flow = 11;
cout << t[0] << endl;
cout << f[0] << endl;
}
If you would run this code, you would notice that t[0] and f[0] are not the same. As I just copied the crucial elements of your code, the reason should still be the same.
What is happening here? When calling
vector<Edge> t = node1->getAdjNodeList();
the adjacency list is returned by reference, which should leave you with a reference to the original list - you should be able to change it's elements, shouldn't you? However, when assigning this reference to the newly allocated vector t, the implicit copy constructor is called, thus t will contain a copy (!) of your vector while you wanted to save a reference.
To get around this problem, you could just have done the following:
vector<Edge> & t = node1->getAdjNodeList();
which saves the reference and does not create a new object.
I can only assume why the pointers happened to be identical between calls to the function: The object probably was copied to the same place every time. Furthermore, note that you increased the value of an object that did not exist anymore - the copy was deleted with the end of the find_edge-call.
It took some time to give an answer to your question as you did not track the problem down yourself. If you had given the example above, I bet your solution would have been there within a matter of minutes. You are encouraged to raise your problems here at stack overflow - however, most members will not be willing to work through a lot of code to identify the problem themselves. That means, high quality answers usually require questions that directly come to the point. (The last paragraph was intended to help you in the future, however, it could be reduced without altering the question).
Apart from that, I would strongly encourage you not to use your objects the way you do. By passing everything as references and making all changes outside the object, you essentially bypass the encapsulation that makes object orientated programming that powerful. For example, it would be much wiser (and would not have given you your problem) if you just had added another function increaseFlow(Edge* to, int increment) to your Node and had done everything within the object.
Hope I could help.