A queue of pointers change its value - c++

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.

Related

Initializing Vector of Structs in Constructor C++

in Class.h
Struct Node
{
int ID;
int position;
}
In class Class.cpp I am initializing vector of structs which leads to core dump error
Class::Class(const branch& branches):mybranches(branches)
{
for (const auto & branch:mybranches)
{
Node* node
node->ID= branch->ID
node->position= branch->position
mynodesvector.push_back(std::move(node));
}
}
However initializing it like this leads to no error
Class::Class(const branch& branches):mybranches(branches)
{
for (const auto & branch:mybranches)
{
Node node
node.ID= branch->ID
node.position= branch->position
mynodesvector.push_back(&node);
}
}
I want to know what is the reason for the core dump error with initializing it as pointer to struct.
You do not create/allocate an object to which node* shall point; so dereferencing node leads to undefined behaviour;
Node* node;
node->ID= branch->ID; // UB here...
However, allocating an object like
Node* node = new Node();
node->ID= branch->ID;
...
should work.
In your second example, you define a Node-object (and not just a pointer to it). So at least accessing its members is save.
Node node; // defines a Node-object.
node.ID= branch->ID; //save
node.position= branch->position; // save
Note, however, that you push_back a pointer to an object with block scope; when you dereference this pointer later, the actual object will be out of scope and you get undefined behaviour then.
mynodesvector.push_back(&node);
I'd suggest to have a look at std::shared_ptr<Node>.
In addition to the answer of #Stefan Lechner:
The version which throws no direct error has a bug which is likely to blow up whenever you try to modify the values in the mynodesvector:
you initialize a struct on the stack and then push its address into a vector. Once an iteration of the for loop has terminated, the Node instance is destructed, but you still have the pointer to it in the vector.
for (const auto & branch:mybranches)
{
{
Node node
node.ID= branch->ID
node.position= branch->position
mynodesvector.push_back(&node);
}
// here, Node is dead, but the pointer to it lives on.
}
In order to find bugs like that that escape your code control I recommend enabling compiler warnings and using appropriate sanitizers.

Why is this returning true?

I started C++ a few hours ago and have been trying to do a simple LinkedList implementation in it to get myself familiar with it, however, I'm stumped as to why this method hasNext() keeps returning true.
#include <iostream>
#include <string>
using namespace std;
struct LinkedNode {
public:
int data;
LinkedNode(int d = 0) {
data = d;
}
void setNext(LinkedNode * linked_node) {
next = linked_node;
}
LinkedNode * getNext() {
return next;
}
bool hasNext() {
return (next != nullptr);
}
private:
LinkedNode * next;
};
int main() {
LinkedNode * linked_list = new LinkedNode(2);
(*linked_list).setNext(new LinkedNode(10));
if (linked_list->getNext()->hasNext()) {
cout << "true";
}
else {
cout << "false";
}
}
This outputs "true", but when I try to access the data since it is supposedly "true" I get the Segmentation fault error, (going to guess it's being raised since I'm trying to get a value that doesn't exist), from linked_list->getNext()->getNext()->data; Can somebody explain why?
The constructor of LinkedNode does not initialise the next member.
That means it is uninitialised. It is not set to zero by default. In fact, accessing its value (before initialising it, or assigning a value to it) gives undefined behaviour.
Set next to be nullptr within the constructor.
You are not initializing next. By default allocating memory just changes a data structure storing information about what memory block is allocated. It does not change the content of this memory block. So you can consider the next pointer be of random data. And since random data is different than null pointer hasNext returns true but when you access the data it is very likely that the random data is interpreted as a pointer into some memory that either does not exist or your application does not has the right to access too. Therefore the result in segmentation / page fault.
To verify this truth just do not initialize data as well, create some nodes and read the data (or even the next pointer). This way you see the randomness which is basically just left overs of content the memory block once hold before it was freed.
PS: Memory blocks are freed and dynamically spliced and combined based on algorithms you can learn. Check out malloc and some other implementations and see the Wikipedia about memory allocation.
You must initialize the value of next to nullptr. By default, the value is undefined (garbage).
Check out member initializer lists:
LinkedNode(int d = 0)
: data( d )
, next( nullptr )
{
}
Or simply assign the values directly in the constructor body:
LinkedNode(int d = 0)
{
data = d;
next = nullptr;
}

Pointers and reference issue

I'm creating something similar to structure list. At the beginning of main I declare a null pointer. Then I call insert() function a couple of times, passing reference to that pointer, to add new elements.
However, something seems to be wrong. I can't display the list's element, std::cout just breaks the program, even though it compiler without a warning.
#include <iostream>
struct node {
node *p, *left, *right;
int key;
};
void insert(node *&root, const int key)
{
node newElement = {};
newElement.key = key;
node *y = NULL;
std::cout << root->key; // this line
while(root)
{
if(key == root->key) exit(EXIT_FAILURE);
y = root;
root = (key < root->key) ? root->left : root->right;
}
newElement.p = y;
if(!y) root = &newElement;
else if(key < y->key) y->left = &newElement;
else y->right = &newElement;
}
int main()
{
node *root = NULL;
insert(root, 5);
std::cout << root->key; // works perfectly if I delete cout in insert()
insert(root, 2);
std::cout << root->key; // program breaks before this line
return 0;
}
As you can see, I create new structure element in insert function and save it inside the root pointer. In the first call, while loop isn't even initiated so it works, and I'm able to display root's element in the main function.
But in the second call, while loop already works, and I get the problem I described.
There's something wrong with root->key syntax because it doesn't work even if I place this in the first call.
What's wrong, and what's the reason?
Also, I've always seen inserting new list's elements through pointers like this:
node newElement = new node();
newElement->key = 5;
root->next = newElement;
Is this code equal to:
node newElement = {};
newElement.key = 5;
root->next = &newElement;
? It would be a bit cleaner, and there wouldn't be need to delete memory.
The problem is because you are passing a pointer to a local variable out of a function. Dereferencing such pointers is undefined behavior. You should allocate newElement with new.
This code
node newElement = {};
creates a local variable newElement. Once the function is over, the scope of newElement ends, and its memory gets destroyed. However, you are passing the pointer to that destroyed memory to outside the function. All references to that memory become invalid as soon as the function exits.
This code, on the other hand
node *newElement = new node(); // Don't forget the asterisk
allocates an object on free store. Such objects remain available until you delete them explicitly. That's why you can use them after the function creating them has exited. Of course since newElement is a pointer, you need to use -> to access its members.
The key thing you need to learn here is the difference between stack allocated objects and heap allocated objects. In your insert function your node newElement = {} is stack allocated, which means that its life time is determined by the enclosing scope. In this case that means that when the function exits your object is destroyed. That's not what you want. You want the root of your tree to stored in your node *root pointer. To do that you need to allocate memory from the heap. In C++ that is normally done with the new operator. That allows you to pass the pointer from one function to another without having its life time determined by the scope that it's in. This also means you need to be careful about managing the life time of heap allocated objects.
Well you have got one problem with your Also comment. The second may be cleaner but it is wrong. You have to new memory and delete it. Otherwise you end up with pointers to objects which no longer exist. That's exactly the problem that new solves.
Another problem
void insert(node *&root, const int key)
{
node newElement = {};
newElement.key = key;
node *y = NULL;
std::cout << root->key; // this line
On the first insert root is still NULL, so this code will crash the program.
It's already been explained that you would have to allocate objects dynamically (with new), however doing so is fraught with perils (memory leaks).
There are two (simple) solutions:
Have an ownership scheme.
Use an arena to put your nodes, and keep references to them.
1 Ownership scheme
In C and C++, there are two forms of obtaining memory where to store an object: automatic storage and dynamic storage. Automatic is what you use when you declare a variable within your function, for example, however such objects only live for the duration of the function (and thus you have issues when using them afterward because the memory is probably overwritten by something else). Therefore you often must use dynamic memory allocation.
The issue with dynamic memory allocation is that you have to explicitly give it back to the system, lest it leaks. In C this is pretty difficult and requires rigor. In C++ though it's made easier by the use of smart pointers. So let's use those!
struct Node {
Node(Node* p, int k): parent(p), key(k) {}
Node* parent;
std::unique_ptr<Node> left, right;
int key;
};
// Note: I added a *constructor* to the type to initialize `parent` and `key`
// without proper initialization they would have some garbage value.
Note the different declaration of parent and left ? A parent owns its children (unique_ptr) whereas a child just refers to its parent.
void insert(std::unique_ptr<Node>& root, const int key)
{
if (root.get() == nullptr) {
root.reset(new Node{nullptr, key});
return;
}
Node* parent = root.get();
Node* y = nullptr;
while(parent)
{
if(key == parent->key) exit(EXIT_FAILURE);
y = parent;
parent = (key < parent->key) ? parent->left.get() : parent->right.get();
}
if (key < y->key) { y->left.reset(new Node{y, key}); }
else { y->right.reset(new Node{y, key}); }
}
In case you don't know what unique_ptr is, the get() it just contains an object allocated with new and the get() method returns a pointer to that object. You can also reset its content (in which case it properly disposes of the object it already contained, if any).
I would note I am not too sure about your algorithm, but hey, it's yours :)
2 Arena
If this dealing with memory got your head all mushy, that's pretty normal at first, and that's why sometimes arenas might be easier to use. The idea of using an arena is pretty general; instead of bothering with memory ownership on a piece by piece basis you use "something" to hold onto the memory and then only manipulate references (or pointers) to the pieces. You just have to keep in mind that those references/pointers are only ever alive as long as the arena is.
struct Node {
Node(): parent(nullptr), left(nullptr), right(nullptr), key(0) {}
Node* parent;
Node* left;
Node* right;
int key;
};
void insert(std::list<Node>& arena, Node *&root, const int key)
{
arena.push_back(Node{}); // add a new node
Node& newElement = arena.back(); // get a reference to it.
newElement.key = key;
Node *y = NULL;
while(root)
{
if(key == root->key) exit(EXIT_FAILURE);
y = root;
root = (key < root->key) ? root->left : root->right;
}
newElement.p = y;
if(!y) root = &newElement;
else if(key < y->key) y->left = &newElement;
else y->right = &newElement;
}
Just remember two things:
as soon as your arena dies, all your references/pointers are pointing into the ether, and bad things happen should you try to use them
if you ever only push things into the arena, it'll grow until it consumes all available memory and your program crashes; at some point you need cleanup!

how to make a function return a structure pointer in c++

I want to make the function return the address of a particular node .but the compiler is
not detecting the node datatype structure i created.
struct node
{
int data;
node *link;
};
node *header,*current;
node traverse(int pos);
node *Linkedlist::traverse(int pos)
{
int location = 0;
current->link = header->link;
node *address = new node;
address->data = NULL;
address->link = NULL;
while(current->link != NULL)
{
if(location == pos)
{
cout <<current->link->data <<" "<< endl;
address->link=current->link;
}
location ++;
current->link = current->link->link;
}
return address->link;
}
Change
return *address;
to
return address;
As address is a pointer variable to node, you need to simply return the variable.
A * preceding a pointer variable is an explicit referencing, which means to get the value pointed by the pointer variable address. This is antagonistic to what the operator & would have done, fetch the address of a variable.
return address;
So its logical that you should return the variable instead of returning the value pointed by the variable.
Note, care needs to be taken by the caller of traverse to free the memory explicitly by calling delete else this would result in memory leak. This is because of a potential design issue, where you have allocated a heap object inside a local scope and returned the address.
node * foo = Linkedlist::traverse(n);
...............
delete foo;
You could have simply created the object in the heap or add it as a class member, where in the former case, you can easily transfer the ownership of the object from one scope to another, where in the second case, the lifetime of the object would have been controlled by the object Linkedlist

Passing a object by reference in c++

This is a noobie question, but I'm not sure how to pass by reference in C++. I have the following class which sets up a Node and a few functions.
class Node
{
public:
Node *next;
int data;
Node(int dat)
{
next = NULL;
data = dat;
}
Node* getNext()
{ return next; }
void setNext(Node *n)
{ next = n;}
void reverse(Node *root)
{
Node *previous = NULL;
while(root != NULL)
{
Node *next = root->getNext();
root->setNext(previous);
previous = root;
root = next;
}
root = previous;
}
};
Now, the purpose of my little class is to create a singularly linked list and have the ability to reverse it. And it seems to work fine, if I return the node named 'previous' at the end of reverse.
But look at my main function:
int main()
{
Node *root = new Node(1);
Node *num2 = new Node(2);
Node *num3 = new Node(3);
Node *num4 = new Node(4);
root->setNext(num2);
num2->setNext(num3);
num3->setNext(num4);
root->printList();
root->reverse(root);
root->printList();
return 0;
}
printList() was omitted for sake of space, but it just prints a list given a node. The problem is, when root->reverse(root) is called, root doesn't actually end up pointing to 'previous'.
The output would be this:
1
2
3
4
// the value of previous from the reverse function is 4
1
I really don't understand the output. Anyone care to explain what's happening? (Why isn't the list reversed even though if I did something like this root = root->reverse(root) where reverse returns previous, it would) why is it that root now only points to itself? I'm new to c++ and appreciate your help!
C++ has support for reference semantics. Therefore, for a given function:
void foo(Bar& bar);
To pass by reference you do:
int main() {
Bar whatsit;
foo(whatsit);
return 0;
}
That's it!
This is commonly confused with passing a pointer, where for a function such as:
void foo(Bar* bar);
You would do:
int main() {
Bar whatisit;
foo(&whatsit);
return 0;
}
The difference is mostly a matter of semantics:
- A reference is always valid. There is no reason to check for a NULL pointer.
- A pointer could be NULL, and as such, should be checked.
It is, however, possible for a reference to refer to a NULL pointer, however, if the programmer decides to be evil and abuse reference semantics, but the principle remains.
You aren't passing by reference. You are passing a copy of the pointer. This copy still points to the same node, but it is still just a copy with local scope. Basically it is another pointer pointing to the node that the pointer in main is pointing to (ha!). At the end of your function, your assignment is assigning previous to this pointer copy, and then the function ends and the copy goes out of scope. Your pointer in main remains unchanged.
The reason returning/assigning the pointer worked is that this copy which has been set to what you want is returned and assigned to your pointer in main.
You can fix this in a multitude of ways. Pass a reference to your pointer (ugly imo), use references, or return root and do an assignment.
To pass a pointer by reference you can declare reverse as:
void reverse(Node*& root) {
// ...
}