Strange behaviour of linked list with struct - c++

Basically I created a linked list with struct and a function to add new node to the beginning.
I added 4 nodes to the linked list and read it with a for loop. But the out put is strange
#include <iostream>
using namespace std;
struct Lin{
int val;
Lin* nex;
};
Lin ext (Lin orig, int nod) {
Lin fresh = {nod, &orig};
return fresh;
};
int main(){
Lin x;
x.val=15;
x=ext(x,25);
x=ext(x,35);
x=ext(x,45);
for (int i = 0; i < 4; i=i+1) {
cout <<x.val<< endl;
x = *x.nex;
}
}
Output is:
45
35
-72537468
892483373
Segmentation fault (core dumped)
The first 2 number is correct, but the 3rd is wrong.
Can someome explain what actually happened?

x is stored on the stack, and is not initialized, so x.nex is garbage (and not even NULL).
fresh is stored on the stack, too. It is initialized but unfortunately, orig is stored on the stack as well, and both live only during the call. ext returns a copy of `fresh.
The code looks like you’re more familiar with languages where everything is a reference (like JS, C#, many others). In C/C++ that’s not the case, you have to use pointers explicitly. More like:
Lin *ext (Lin *orig, int nod) {
return new Lin{nod, orig}; // Lin(nod, orig) on pre-C++11 systems
}
int main() {
Lin *x = nullptr; // NULL on pre-C++11 systems
x = ext(x, 15);
...
for (Lin *y = x; y; y = y->nex)
cout << y->val << endl
UPDATE.
I forgot to mention the list structure. It is a chain, where last node’s nex is NULL (that’s special pointer-to-nothing in C/C++; can also be spelled nullptr in modern C++).
As JHBonarius noticed I forgot to describe how to free that list (otherwise it will remain in memory till program end). It is done in a similar loop; the trick here is to save value of nxt before deleting the node
for (Lin *y = x; y; ) {
Lin *next = y->nxt;
delete y; // deletes the object `y` points to,
// so accessing `y->nxt` is not allowed anymore,
// but accessing `next` is
y = next;
}
Note that x becomes a dangling (i.e. pointing to arbitrary memory location) pointer when the first node is deleted, so it’s better to set it to NULL afterwards (as pointer can be checked for being NULL but not for being dangling; also dereferencing NULL is almost certain crash while dereferencing dangling pointer leads to obscure problems [sometimes crashes too] appearing in unrelated program parts).

Your problem is here:
Lin fresh = {nod, &orig};
You're grabbing the address of orig, which is declared as:
Lin ext (Lin orig, int nod) {
So orig is actually a Lin copy! It'll go out of scope when the function finishes, so you'll be left with an invalid pointer and undefined behavior.
You can avoid this by passing by reference instead of by copy:
Lin ext (Lin &orig, int nod) {
But then you're passing the same Lin object (x) every time, so &orig will be the same address every time. You'll need multiple different Lin objects with different addresses. If you want to continue avoiding dynamically allocated memory, that could look like:
int main(){
Lin x;
x.val = 15;
x.nex = nullptr; // Don't forget to null your tail's next!
Lin x2 = ext(x,25);
Lin x3 = ext(x2,35);
Lin x4 = ext(x3,45);
for (Lin i = x4; i.nex; i = *i.nex) {
cout << i.val << endl;
}
}

Lin ext (Lin orig, int nod) {
Lin fresh = {nod, &orig};
return fresh;
};
This - Lin orig is passed as a COPY of the original data, taking a reference to this will at some point mess up the memory as your are referencing the memory address of a temporary variable.
I would pass in a pointer myself
such that:
#include <iostream>
#include <string>
struct Lin
{
int val;
Lin* nex;
Lin(int value = 0, Lin *next = NULL)
: val(value)
, nex(next)
{}
};
Lin* ext(Lin *orig, int nod)
{
return new Lin(nod, orig);
};
int main()
{
Lin *pi_x = new Lin(15);
pi_x = ext( pi_x, 25 );
pi_x = ext( pi_x, 35 );
pi_x = ext( pi_x, 45 );
std::cout << "List:" << std::endl;
for(Lin *lin = pi_x; lin != NULL; lin = lin->nex )
{
std::cout << lin->val << std::endl;
}
std::cout << "------" << std::endl;
return 0;
}
Last but not least - you are looping though pointers - memory adresses.
The linked list is modelled by having a null pointer as being the terminating element (next is null)
The struct you are creating should atleast start with a memory assignment of some sort such that you dont have random adresses set in the pointer of Lin and you should also guarantee that you dont dereference a nullpointer (ie. *x.nex)
--
I redid my implementation - as comments correctly state the variable was stack allocated and the same address was used for the 'node factory' method.
Now by calling 'new' the memory is dynamically allocated (heap) and using a pointer will just update the memory address when using the assignment operator instead of copying the contents of the struct as before with the stack allocated memory.
doing a for loop with NULL check for termination can be a risky thing - and as comments suggest if the data does not adhere to the rules expected there is a risk for infinite loops.
Results of running the revised code
List:
45
35
25
15
------
With respect to the memory leaks it is possible to change the implementation to use smart pointers which can be found in ´<memory>´
And then swap any raw Lin pointers with
#include <memory>
std::shared_ptr<Lin> ptr;
ptr = std::make_shared<Lin>(0, NULL);
// Getting raw pointer from smart_pointer
Lin *raw = ptr.get();

Related

Shared_ptr instance is not set for an object as expected

I have a struct A which has a member another struct C. So A with c1Ptr_ as member.
I use 2 structs S and N. N has as member A, a_ and S has as member C, c_.
After I instantiated A and create for S a c object using the created A object and I pass the created A object to N I would expect to have the A->c1Ptr_ in N as well.
Thank you.
#include <iostream>
#include <memory>
using namespace std;
struct C1
{
C1(int x):x_(x)
{
std::cout<<"-C1: x_: " << x_ << std::endl;
}
int x_;
~C1()
{
std::cout<<"-DC1: x_: " << x_ << std::endl;
}
};
using C1ptr = std::shared_ptr<C1>;
struct A
{
C1ptr c1Ptr;
};
struct S
{
S(C1ptr& c1Ptr):c1Ptr_(c1Ptr)
{
}
C1ptr c1Ptr_;
};
struct N
{
N(std::shared_ptr<A> a):a_(a)
{
}
std::shared_ptr<A> a_;
};
int main()
{
std::shared_ptr<A> a = std::make_shared<A>();
S s(a->c1Ptr);
N n(a);
s.c1Ptr_ = std::make_shared<C1>(12);
if (n.a_->c1Ptr)
{
std::cout<<"c1Ptr is set for N\n";
}
else
{
std::cout<<"c1Ptr is NOT set for N\n"; // why c1Ptr is not set for n.a_ ?
}
return 0;
}
shared_ptr doesn't share a pointer, it shares ownership of a pointer.
This means that you can change individual shared_ptr to point to other things, indepnendent of other shared_ptr's, but as soon as there's no shared_ptr pointing at something, that something get's deleted. Think of it as adding a counter to the pointer. When you create, delete or reassign a shared_ptr to something other than nullptr, you will increment or decrement the counter. If the counter reaches 0 (usually on a delete) then it also deletes the pointer.
In your case you are copying a nullptr from a. So you have two shared_ptr both storing nullptr. Then you change one of them to point to a new thing (12). This won't change anything else in memory, or specifically the value of other shared_ptrs.
You can try to work this out on your own by drawing the objects a, s, and n and their contents, and what their contents point to:
auto a = std::make_shared<A>(); // a(c1Ptr_ = null)
S s(a->c1Ptr_); // a(c1Ptr_ = null), s(c1Ptr_ = null)
N n(a); // a(c1Ptr_ = null), s(c1Ptr_ = null), n(a_ = a)
// [n.a_ points to a]
After this initial block of instructions:
a and s have their shared pointer members c1Ptr_ with a value of nullptr.
n has its shared pointer member a_ pointing to the object a.
s.c1Ptr_ = std::make_shared<C1>(12); // (1) a(c1Ptr_ = null), s(c1Ptr_->x_ = 12 ), n(a_ = a)
// [and you modify s]
if (n.a_->c1Ptr_) {
std::cout << "c1Ptr is set for N\n\n";
}
else {
std::cout << "c1Ptr is NOT set for N\n\n"; // (1)
}
Here:
you just modify s.c1Ptr_, but that doesn't affect a, and ultimately, n.
s.c1Ptr_ was originally set to point to the same C1 object as a.c1Ptr_ (actually, nullptr); now you're just making it point to something else.
a->c1Ptr_ = std::make_shared<C1>(15); // (2) a(c1Ptr_->x_ = 15 ), s(c1Ptr_->x_ = 12 ), n(a_ = a)
// [and you modify a]
if (n.a_->c1Ptr_) {
std::cout << "c1Ptr is set for N\n\n"; // (2)
}
else {
std::cout << "c1Ptr is NOT set for N\n\n";
}
What would have happened if you had changed a->c1Ptr_ instead? Since n->a_ points to a and we are modifying a, n->a_->c1Ptr_ is also set.
[Demo]

Frustrating pointer error

For the life of me, I can't figure out what is going wrong. I know the error is occurring in the function marked displayQueue below, but all the syntax and logic seems correct.
Visual studio is giving me the error: "Unhandled exception at 0x00215A86 in ex11_1.exe: 0xC0000005: Access violation reading location 0xCDCDCDE1." But really, I have no idea what this is referring to...
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
struct QueueNode {
string data;
QueueNode *link;
};
typedef QueueNode* QueueNodePtr;
class Queue {
public:
// Constructors/Destructor.
Queue();
Queue(const Queue& aQueue);
// Accessors.
bool empty() const;
void displayQueue ();
// Mutators.
void add(string item);
string remove(); // This should probably be replaced with pop and top - especially for displayQueue... empty() in functions can be replaced with count == 0. Yes, I will do this.
private:
QueueNodePtr front; // Points to head of linked-list queue.
QueueNodePtr back; // Points to tail of linked-list queue.
size_t count;
};
int main () {
Queue myQueue;
myQueue.add("abc");
myQueue.add("def");
myQueue.add("ghi");
myQueue.displayQueue(); // The error is here somewhere. abc is printed and but nothing else.
system("pause");
return 0;
}
Queue::Queue() {
front = NULL;
back = NULL;
count = 0;
}
Queue::Queue(const Queue& aQueue) {
front = aQueue.front;
back = aQueue.back;
count = aQueue.count;
}
bool Queue::empty() const {
if (count == 0) {
return 1;
} else {
return 0;
}
}
void Queue::displayQueue () {
// There is a problem here somewhere...
QueueNodePtr here = front;
for (int i = 0; i < count; i++) {
cout << here->data << endl;
here = here->link;
}
}
void Queue::add(string item) {
QueueNodePtr newNode;
newNode = new QueueNode;
if (count == 0) {
// If inserted in an empty queue, back and front point to same element.
newNode->data = item;
// newNode->link = NULL; // Not sure this part is even necessary.
back = newNode;
front = back;
} else {
// Otherwise, leave front pointer where it's at.
newNode->data = item;
newNode->link = back->link;
back = newNode;
}
count ++;
}
string Queue::remove() {
string returnString;
if (count == 0) {
return returnString;
} else if (count == 1) {
returnString = front->data;
front = NULL;
back = front;
count--;
return returnString;
} else {
returnString = front->data;
front = front->link;
count--;
return returnString;
}
}
EDIT: If anyone can give me any tips on using the debugger to solve problems like this, or give me a link that might explain this it would be greatly appreciated.
The error is on this line, but for the sake of learning, I won't give the correct version, just a few hints:
newNode->link = back->link;
At the point where this code is being executed, which node does back point to? What does its link point to? Whose node's link do you need to modify?
As for finding this yourself, you could have used the debugger to figure out which line causes the crash; this would have indicated that something is wrong with a link value.
P.S. Your copy constructor doesn't actually copy the linked list; it just creates a new Queue object that points to the same linked list, so if you add an element to the copy, it will show up in the original Queue.
An access violation at address 0xCDCDCDCD means that your program loaded a pointer from uninitialized storage and then dereferenced it. Microsoft's debugging allocator uses this pattern for newly allocated uninitialized storage, and in a suitable compilation mode, also for stack locations. If you treat such uninitialized storage as a pointer variable, the pattern is recognizeable in that pointer. Moreover, it is almost certainly an invalid pointer that will trigger an exception. So the benefit is that the use of the invalid pointer is caught quickly, and the pattern tells you that the cause is quite likely uninitialized storage (though this is not 100% conclusive).
For example:
struct contains_pointer { char *str; } *ptr = malloc(sizeof *ptr);
strcpy(ptr->str, "abc"); // ptr->str is uninitialized
Or:
int *pint;
*pint = 0; // pint is uninitialized
To have the compiler and library overwrite uninitialized storage with a pattern like CDCDCD... can be quite helpful. You should pinpoint the location of the crash with the debugger, and then work backward from there: where did the pointer value originate and why wasn't it initialized.
(A bad pointer to the address CDCDCDCD could result in other ways: sheer fluke (unlikely) or a use-after-free bug: the program frees some memory but continues to keep a pointer to it, without using it for a while. The memory is then re-allocated to some other part of the program, and marked uninitialized, and by chance, the original user of the pointer makes a use of it, loading a pointer value from the memory. At that moment, a CDCDCDCD pointer results, so it looks like a use-before-init bug, when in fact it's a use-after-free bug. Debugging based on "memory poisoning" patterns is not accurate!)

C++ problems with pointers while creating Nodes

So I was trying to convert a BST to DLL using some given functions which I had to use. While doing that, I kept getting segmentation faults. As I tried debugging it, I finally came to this. I have written a very simple test script below.
What I knew about pointers is it is passed by reference, as in if I am changing the value/object to which the passed pointer points to, it is reflected in my original calling function.
Why is it that when I create a new Node and then pass the pointer (myf), it works, but when I just pass the pointer and create the new Node inside the function, it shows segmentation fault (myf2)?
If this is because the new node goes out of scope, check the function "myf" again. I have created a new Node which is pointed to by my original node. And the value of this is retained after the function call ends. Doesn't this too go out of scope then?
I have some basic fundamental problems with pointers it appears and this would really help. Thanks
#include<iostream>
using namespace std;
class Node
{
public:
int val;
Node *left;
};
void myf(Node *a)
{
a->left = new Node();
a->left->val = 20;
a->val = 15;
}
void myf2(Node *a)
{
a = new Node();
a->val = 35;
}
int main()
{
Node *a = NULL, *b = NULL;
a = new Node();
a->val = 5;
myf(a);
cout << "New value of a = " << a->val << endl;
cout << "left value of a = " << a->left->val << endl;
myf2(b);
cout << "New value of b = " << b->val << endl;
}
Your problem is, your pointer isn't being set to b, to do so, you'd need to edit myf2 to something like this:
void myf2(Node **a)
{
*a = new Node();
(*a)->val=35;
}
And call myf2 like so:
myf2(&b);
And that should solve your problem, I believe.
Don't think of Node *b as only a pointer, think of it as an integer as well, because that's what a pointer breaks down to, an integer pointing to a space in memory.
So you pass a pointer of the pointer(an integer) to the function.
Another example would be:
void myfunction(int *i) {
*i = 5;
}
int main(int argc, char** argv) {
int x;
myfunction(&x);
cout << x << endl;
return 0;
}
But that's using an actual integer.
Why is it that when I create a new Node and then pass the pointer (myf), it works,
Node *a:
main() makes it point it to a block of memory, you pass that address to myf, you update the memory in that block. It works!
But when I just pass the pointer and create the new Node inside the function, it shows segmentation fault (myf2)?
Node *b:
main() doesn't assign it anything, it is pointing to NULL, myf2() get just the address that is NULL, you create another pointer b (not the same as that in main() ), make it points to some block of memory, but it doesn't update what your original b in main() points to, which is still pointing to NULL. Hence SEGFAULT.
Essentially you are trying two different valid approaches, this is the right way:
Case 1.
main()
{
Node* a = NULL;
a = new Node(); //make 'a' point to some valid block of memory
myf(a); // here you are passing the address of the memory block of type Node
cout << "New value of a = " << a->val << endl; //and this is valid since 'a' points to a valid address
}
void myf(Node *a)
{
a->left = new Node();
a->left->val = 20; // Since the address that you got here is valid, you can make changes here, and in main() Node* a is aware of this address
a->val = 15;
}
Case 2.
main()
{
Node* b = NULL;
myf2(&b); // here since b points to NULL, you have to send the address where this NULL is stored so that the called functon can upadte this NULL to something meaningful
cout << "New value of b = " << b->val << endl; // this is correct, because we changed what 'b' pointed to from NULL to a valid block of memory of type 'Node'
}
void myf2(Node **a) //It is a double pointer here because you need to update what it points to, curently it holds NULL
{
*a = new Node(); // Make it point to a valid address, remember main() has track of 'a',
*a->val = 35; // Now if you make any changes to the blok that 'a' points to, main() will have account of it
}
You need to return the reference of Node *a to which you have dynamically allocated memory..
Node* myf(Node *a)
{
a->left = new Node();
a->left->val=20;
a->val=15;
return a;
}
In main ()
a = myf(a);
previously a in main() is not pointing to memory allocated in myf() function...
Receive your Node ptr by reference as below..
void myf2(Node *&a) //<-- Notice & in function signature.
In your current code, you are passing a (Node*) by value, so, whatever changes done in the function will not reflect outside of function and accessing b->val (null ptr access) will be a segment fault

Code for Huffman tree using std::unique_ptr not working

I'm working on building a Huffman encoder for a homework assignment, and I need to know why my code isn't working. I've asked elsewhere on an earlier version, and got a tip to use std::unique_ptr so that the nodes referenced by my pointers won't be deleted from memory when they're deleted from the vector.
This is what I have so far:
#include <iostream> // Allows the use of std::cout >> and std::cin <<.
#include <string> // Allows the use of getline().
#include <fstream> // Allows the use of file I/O.
#include <utility> // Allows the use of std::bitset.
#include <vector> // Allows the use of vectors.
#include <algorithm> // Allows the use of std::sort().
#include <memory> // Allows the use of std::unique_ptr.
struct node
{
char data;
int frequency;
std::bitset<1> code;
node *left;
node *right;
bool operator<(const node &temp) const {return frequency < temp.frequency;}
};
std::vector<node> nodeVector;
void getHuffmanData()
{
std::ifstream inStream;
int size;
int tempFrequency;
char tempData;
node tempNode;
inStream.open("huff-source.txt");
if (inStream.fail())
{
std::cout << "Failure opening input file.\n";
exit(1);
}
inStream >> size;
while (inStream.peek() != EOF)
{
inStream >> tempData;
inStream >> tempFrequency;
tempNode.data = tempData;
tempNode.frequency = tempFrequency;
nodeVector.push_back(tempNode);
}
inStream.close();
}
node buildHuffmanTree() // Returns the root node, which points to all other nodes.
{
node tempNode;
node *x, *y;
std::unique_ptr<node> a (new node);
std::unique_ptr<node> b (new node);
while (!nodeVector.empty())
{
std::sort(nodeVector.begin(), nodeVector.end());
*a = nodeVector.front();
x = a.release();
tempNode.left = x;
nodeVector.erase(nodeVector.begin());
*b = nodeVector.front();
y = b.release();
tempNode.right = y;
nodeVector.erase(nodeVector.begin());
tempNode.frequency = x->frequency + y->frequency;
nodeVector.push_back(tempNode);
std::sort(nodeVector.begin(), nodeVector.end());
if (nodeVector.size() == 1) {break;}
}
return tempNode;
}
int main()
{
node test;
getHuffmanData();
test = buildHuffmanTree();
std::cout << "Press 'Enter' to continue...";
std::cin.get();
return 0;
}
My sample input file, is as follows:
4
a 119
b 20
c 44
d 127
Now, the error message I'm getting in Xcode occurs after it runs once through buildHuffmanTree(). It says 'Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)' at the line containing '*a = nodeVector.front();'. How would I go about correcting the loop so that the function can return a proper tree, illustrated like this:
310
/ \
127 183
d / \
64 119
/ \ a
20 44
b c
You are trying to write to a dereferenced null pointer.
Let me step through your code to show you the error.
node buildHuffmanTree() // Returns the root node, which points to all other nodes.
{
node tempNode;
node *x, *y;
std::unique_ptr<node> a (new node); // a now points to a node in the heap
std::unique_ptr<node> b (new node); // b now points to a node in the heap
while (!nodeVector.empty())
{
std::sort(nodeVector.begin(), nodeVector.end());
*a = nodeVector.front(); // you copy the first node in the vector into the node
// on the heap pointed to by a
x = a.release(); // x now points to the node on the heap pointed to by a
// a now holds a nullptr and will not delete the node on the heap
tempNode.left = x; // tempNode.left now points to the node on the heap
nodeVector.erase(nodeVector.begin());
. . .
tempNode.frequency = x->frequency + y->frequency;
nodeVector.push_back(tempNode);
std::sort(nodeVector.begin(), nodeVector.end());
if (nodeVector.size() == 1) {break;}
}
return tempNode;
}
Now we go through the while loop again
while (!nodeVector.empty())
{
std::sort(nodeVector.begin(), nodeVector.end());
*a = nodeVector.front(); // a now holds a nullptr, so this is BAD
. . .
}
I believe you do not fully understand the use of std::unique_ptr.
You probably want a collection of std::unique_ptrs to all your node objects
to persist throughout your program so you have a unique set of nodes that will not disappear.
To link these nodes into your tree, use regular pointers (or maybe shared).
Unique pointers should be used when the object/code block containing the pointer
has sole responsibility to delete the allocated memory pointed to by the pointer.

Help with first C++ class/pointers

Hey guys, I taught myself PHP a few years back and am now in college and am relatively well versed in Java (and by that I really mean I'm a beginner but did my data structures course in it. I'll be taking Algorithms next semester)
In any case...I want to learn C++ and stumbled upon this:
http://newdata.box.sk/bx/c/
What is really tripping me up right now is pointers...I THINK I get the theory but a really simple "program" isn't running right. It compiles but then there's a memory error.
I've decided to purchase C++ Primer after doing a few searches here on SO so it'll get here on Friday. Until then, can anyone tell me what is (horribly) wrong with this simple code:
class Number {
public:
string *owner;
int getNum() {
return *num;
}
int getTwice() {
return *twice;
}
Number(int our_num, string me) {
*num = our_num;
*twice = 2 * *num;
*owner = me;
}
private:
int *num;
int *twice;
};
int main()
{
Number *nbr3 = new Number(3,"Bob");
cout << nbr3->getNum() << endl;
cout << nbr3->getTwice() << endl;
cout << nbr3->owner << endl;
delete nbr3;
system("PAUSE");
return 0;
}
The errors appear in the constructor...like the *num=our_num part.
But isn't that line saying "set the value of the num pointer to our_num"? That IS what I want!
Thanks for helping with what I know to be a very silly and fundamental error...
You didn't allocate memory locations to point to for num, twice,owner. So, in your constructor -
Number(int our_num, string me) {
num = new int;
twice = new int;
owner = new string;
*num = our_num;
*twice = 2 * (*num);
*owner = me;
}
Since, the class is managing resources, class Number should follow -Rule of Three
Edit 1
Pointers are like any other variables but holds a memory address. Just declaring int* ptr; doesn't mean that ptr is pointing a to valid memory location right away. You should assign/initialize it to where it should point to.
So,
int *ptr;
int num = 10;
ptr = &num; // ptr points to num location
int *ptr2 = new int; // The operator returns a memory location from free store that can hold an integer.
*ptr2 = 10; // Now, store 10 in the location ptr2 is pointing to.
// ......
delete ptr2; // You should return the resources back to the free store since we are managing resources.
Hope it helps to an extent.
This is the problem:
Number(int our_num, string me) {
*num = our_num;
*twice = 2 * *num;
*owner = me;
}
private:
int *num;
int *twice;
In your class you have declared num and twice to be pointers, but they do not point
to anything. Doing *num = our_num doesn't change the pointer instead what that means is that you are derefencing what num is pointing to in order to assign the value contained in our_num. This will cause a crash since num is some random value.
In order to fix this set the pointer to point to an int first.
e.g
int myints[2];
num = myints
twice = myints+1;
then you can do
*num = our_num
so when you write
int *num; you are telling the compiler that num will contain an address.
when you use num you are in fact handling the address.
when you write *num you are referencing the data that is at the address num.
num and twice don't point to anything. In the constructor of the class you need num=new int and twice=new int, and in the destructor you need to delete them