C++ problems with pointers while creating Nodes - c++

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

Related

Strange behaviour of linked list with struct

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();

Pointers and pointers to reference

Having a structure
struct Person{
Person( int i):id(i){};
Person * next;
int id;
};
class Test{
public:
void addList( Person *&f , Person *&l , int i){
Person *tmp = new Person(i);
if( f == nullptr ){
f = tmp;
l = tmp;
return;
}
first -> next = tmp;
last = tmp;
}
void addArr( int *arr , int i ){
arr[index++] = i;
}
void print( ){
for( int i = 0; i < index; i ++)
cout << arr[i] << " ";
cout << endl;
}
Person *first = nullptr;
Person *last = nullptr;
int index = 0;
int *arr = new int[10];
};
function addList add node into linked list and addArr adds element into arr.
My question is about pointer and reference pointer.
in
void addList( Person *&f , Person *&l , int i){
Person *tmp = new Person(i);
if( f == nullptr ){
f = tmp;
l = tmp;
return;
}
first -> next = tmp;
last = tmp;
}
I need to pass pointer as reference. Otherwise , the local copy of pointer would be changed not outer. I assume compilator creates something like
Person *temporary = new Person(*f);
But would I not have to pass array by reference?
I am quite confused by this fact.
But would i do not have to pass array by reference?
Not in this case, by passing your Person pointer by reference in the addList function, you are able to alter the pointer itself. That is like saying, "Pointer, use a different address". This is possible, as it was passed by reference.
Whereas in your addArr function, you are not altering the pointer to the array itself. Rather, you are altering the data that is pointed to. "Pointed to data, use a different value". This data arr is pointing to is the same data outside the scope of the function.
So, no, you don't have to pass the array by reference.

Using pointers vs. address-of operator while copying linked lists in C++ [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 7 years ago.
I made the following linked list structure and printList function. Both functioned correctly:
struct Node{
int data;
Node *np;
};
void printList(Node *x){
cout << x->data << " ";
if (x->np != NULL){
printList(x->np);
}
return;
}
Then I decided to write a recursive function to copy over a linked list. One implementation, returning a pointer value, works...whereas the other, returning an address-of didn't work...I can't for the life of me figure out why this is the case:
This works:
Node * copyList(Node *x){
Node * y = new Node;
y->data = x->data;
if (x->np != NULL){
y->np = copyList(x->np);
}else{
y->np = NULL;
}
return y;
}
This doesn't work:
Node * copyList(Node *x){
Node y = {x->data,NULL};
if (x->np != NULL){
y.np = copyList(x->np);
}
return &y;
}
I'm a little confused as to why. I would assume that given that a pointer essentially refers to a memory address, returning &y would be just as fine...
In the second case the Node y object you are creating will go out of scope when the function call will end. The address you are returning will then be not valid.
As soon as copyList exits, all of its local variables are destroyed; there no longer exists a Node object at the location pointed to by the pointer you return. That memory will likely be used for some other purpose the next time you call a function.
The first function is also invalid because in general the argument that is x can be equal to NULL. So you have undefined behaviour in statement
y->data = x->data;
A correct function can look like
Node * copyList( const Node *x )
{
if ( x == NULL )
{
return NULL;
}
else
{
Node *y = new Node { x->data, copyList( x->np ) };
return y;
}
}
Or even like
Node * copyList( const Node *x )
{
return ( x == NULL ) ? NULL : new Node { x->data, copyList( x->np ) };
}
The same problem exists with function printList. It should be defined like
void printList( const Node *x )
{
if ( x == NULL )
{
std::cout << std::endl;
}
else
{
std::cout << x->data << ' ';
display( x->np );
}
}
As for the second function then apart from this error it returns pointer to a local variable that after exiting the function becomes invalid because the local variable will be deleted.

pointer based linked list gives segmentation error

#include "AirlineReservationSystem.h"
struct test{
int num;
test* tNext;
};
int main()
{
test* a;
a = new test;
a->num = 8;
a->tNext = new test;
test* ptr = a;
ptr = ptr->tNext;
ptr->num = 9;
cout << ptr->num;
ptr = a;
cout << ptr->num;
while ( ptr->tNext != NULL){
ptr = ptr->tNext;
}
cout << ptr->num;
return 0;
}
I am trying to understand here why this code gives a segmentation error. Disregard the include at the start, It does nothing.
I am very very very new at this and trying to understand pointers and linked lists better and make some practice yet i am unable to see what i am doing wrong.
Program itself prints the first two couts but crashed at while statement which means there must be some problem with it, if someone could explain to me what that problem really is and what i am missing, it would be great. Thanks.
You have initialized ptr->num = 9, but you have not initialized ptr->tNext to anything.
Now let's examine the following piece of code:
while ( ptr->tNext != NULL){
ptr = ptr->tNext;
}
Iteration #1:
Most likely ptr->tNext != NULL, so you enter the loop and set ptr = ptr->tNext.
Now ptr is most likely pointing to an invalid memory address.
Iteration #2:
ptr is most likely pointing to an invalid memory address.
Therefore, ptr->tNext would most likely yield an illegal memory access.
When you create the second test, you do not initialize the pointer member in the struct.
This means that it points to some random memory address which is not a test instance (although I heard that some compilers will automatically make it point to NULL, never seen this in action though). Mostly the memory that is reserved for the struct is not cleared by default, so any content that was there remains "in the struct" until you assign it with something else.
If you don't assign it a new value the application will break when trying to dereference the memory.
So to fix this:
struct test{
test() : tNext(NULL) {} // ADD THIS AND ...
~test() { if(tNext) delete tNext; } // ADD THIS AND ...
int num;
test* tNext;
};
int main()
{
test* a;
a = new test;
a->num = 8;
a->tNext = new test;
test* ptr = a;
ptr = ptr->tNext;
ptr->num = 9;
cout << ptr->num;
ptr = a;
cout << ptr->num;
while ( ptr->tNext != NULL){
ptr = ptr->tNext;
}
cout << ptr->num;
delete a; // ADD THIS
return 0;
}
The first line is a constructor that sets the pointer to NULL which will prevent the pointer to point to random memory. The second line is the destructor which will clean up your nested structure recursively.
This behavior is desired because your code will exit from the while giving segmentation fault as your ptr->tNext!=NULL condition is not met at the last node also. So for the last node the ptr is set with a garbage value and hence when ptr->tNext!=NULL is executed, it gives segmentation fault error.
To avoid this, add the following line after ptr->num = 9;
ptr->tNext = NULL;
(1) Probably you are missing initialization of tNext to NULL.
Try changing your definition to:
struct test{
int num;
test* tNext;
test():num(0),tNext(NULL) {} // contructor initializing the members to default values
};
(2) You dont know if ptr is NULL or not inside while condition and in that case it is likely to give segmentation fault. Add null check on ptr in while () as well like this:
while (ptr && ptr->tNext != NULL){ // ptr->tNext is executed only when ptr is valid
ptr = ptr->tNext;
}

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