pointer based linked list gives segmentation error - c++

#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;
}

Related

illegal instruction occur while using pointer and reference

when reading the source codes of realtime_tools::RealtimeBuffer, I got lots of questions about the pointer and reference. The related codes are shown below:
void writeFromNonRT(const T& data)
{
// get lock
lock();
// copy data into non-realtime buffer
*non_realtime_data_ = data;
new_data_available_ = true;
// release lock
mutex_.unlock();
}
To figure out, I tried to code the similar code like:
#include <iostream>
using namespace std;
void pt_ref(int& data)
{
int *ptr;
ptr = &data; // ptr points to "data"
cout << "data's addres: "<< ptr <<"\n"; // print address
}
int main()
{
int x = 3;
pt_ref(x);
cout << "x's address: " << &x;
}
\\ output:
\\ data's addres: 0x7ffe05c17c4c
\\ x's address: 0x7ffe05c17c4c
This code runs well, but it's still different to the source code.
// these 2 lines are different.
*non_realtime_data_ = data;
ptr = &data;
So I tried to change ptr = &data; to *ptr = data;, and ran again the code, the error("illegal instruction") occurred.
Hope someone can answer me, thanks a lot.
PS: I ran the code on the replit online compiler.
I tried to change ptr = &data; to *ptr = data;, and ran again the code, the error("illegal instruction") occurred.
The problem is that the the pointer ptr was uninitialized(and does not point to any int object) and so dereferencing that pointer(which you did when you wrote *ptr on the left hand side) leads to undefined behavior.
int *ptr; //pointer ptr does not point to any int object as of now
*ptr = data;
//-^^^^--------->undefined behavior since ptr doesn't point to any int object
To solve this make sure that before dereferencing ptr, the pointer ptr points to some int object.
void pt_ref(int& data)
{
int var = 10; //int object
//-------------vvvv-------->now ptr points to "var"
int *ptr = &var;
//--vvvv------------------->this is fine now
*ptr = data;
}

Renaming variable yields different results

I wrote a simple function which finds the oldest person in an array of structs. The structure stores information about age and name.
#include <iostream>
struct Person
{
int age;
char name[16];
};
char* oldest(Person* arr, int len)
{
int max = 0;
char* ptr = nullptr;
Person elem;
for (int i = 0; i < len; i++)
{
elem = arr[i];
if (max < elem.age)
{
max = elem.age;
ptr = arr[i].name;
}
}
return ptr;
}
int main()
{
Person list[3] = {
{20, "Alice"},
{70, "Bob"},
{25, "James"}
};
std::cout << oldest(list, 3) << '\n';
}
It yields correct result (namely I see Bob on the screen), but when I use elem instead of arr[i] in the line ptr = arr[i].name; (which is nothing but giving another name to arr[i], right??) the program suddenly starts giving some weird results (unprintable characters). I have no idea why it behaves this way.
For your reference, this is the code that doesn't work:
char* oldest(Person* arr, int len)
{
int max = 0;
char* ptr = nullptr;
Person elem;
for (int i = 0; i < len; i++)
{
elem = arr[i];
if (max < elem.age)
{
max = elem.age;
ptr = elem.name;
}
}
return ptr;
}
ptr = elem.name; assigns to ptr the address of the first element of elem.name (because the arary elem.name is automatically converted to a pointer to its first element). elem.name is of course an array inside elem, and elem is an object with automatic storage duration, meaning it is created automatically in the block it is defined in and it is destroyed when execution of that block terminates. So, when the function return, elem ceases to exist in the C++ model of computing, and a pointer to part of it becomes invalid.
… which is nothing but giving another name to arr[i], right??
No, the statement elem = arr[i]; makes a copy of arr[i] in elem. It does not make elem an alternate name for arr[i]. That copy ceases to exist when the function returns.
If you removed the Person elem; declaration and, inside the loop, used Person &elem = arr[i]; instead of elem = arr[i];, that would define elem to be a reference to arr[i]. Then it would be effectively an alternate name for arr[i], and ptr = elem.name; would set ptr to point to the first element of arr[i].name.
(which is nothing but giving another name to arr[i], right??)
Not right. elem is a distinct object. It is not a name of arr[i].
but when I use elem instead of arr[i] in the line ptr = arr[i].name; ... the program suddenly starts giving some weird results
With that change, you are returning a pointer to (a member of) an automatic variable. When the function returns, the automatic variable is destroyed and the returned pointer will be invalid. When you indirect through the invalid pointer and attempt to access deallocated memory, the beahviour of the program is undefined.

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

How to access the addresses after i get out of the loop?

#include<iostream>
using namespace std;
struct data {
int x;
data *ptr;
};
int main() {
int i = 0;
while( i >=3 ) {
data *pointer = new data; // pointer points to the address of data
pointer->ptr = pointer; // ptr contains the address of pointer
i++;
}
system("pause");
}
Let us assume after iterating 3 times :
ptr had address = 100 after first loop
ptr had address = 200 after second loop
ptr had address = 300 after third loop
Now the questions are :
Do all the three addresses that were being assigned to ptr exist in the memory after the program gets out of the loop ?
If yes , what is the method to access these addresses after i get out of the loop ?
Well the memory is reserved but you have no pointer to the memory so that's whats called a memory leak (reserved memory but no way to get to it). You may want to have an array of data* to save these pointers so you can delete them when you are done with them or use them later.
For starters, there will be no memory allocated for any ptr with the code you have.
int i = 0;
while( i >= 3)
This will not enter the while loop at all.
However, if you are looking to access the ptr contained inside the struct then you can try this. I am not sure what you are trying to achieve by assigning the ptr with its own struct object address. The program below will print the value of x and the address assigned to ptr.
#include<iostream>
using namespace std;
struct data {
int x;
data *ptr;
};
int main() {
int i = 0;
data pointer[4];
while( i <=3 ) {
pointer[i].x = i;
pointer[i].ptr = &pointer[i];
i++;
}
for( int i = 0; i <= 3; i++ )
{
cout<< pointer[i].x << endl;
cout<< pointer[i].ptr << endl;
}
}
OUTPUT:
0
0xbf834e98
1
0xbf834ea0
2
0xbf834ea8
3
0xbf834eb0
Personally, when I know the number of iterations I want to do, I choose for loops and I use while only when I am looking to iterate unknown number of times before a logical expression is satisfied.
I cannot guess what you are trying to achieve...
But Me thinks, you are trying to achieve similar to this....
But, If you want to make linked list using your implementation, you can try this...
#include<iostream.h>
struct data {
int x;
data *ptr;
data()
{
x = -1;
ptr = NULL;
}
};
data *head = new data();
data *pointer = head;
int main() {
int i = 0;
while( i <=3 ) {
data *pointer = new data();
pointer->x = /*YOUR DATA*/;
::pointer->ptr = pointer;
::pointer = pointer;
i++;
}
i=0;
data* pointer = head->next;
while( i <=3 ) {
cout<<pointer->x;
pointer = pointer->ptr;
i++;
}
system("pause");
}
This will print , the elements in the linked list;

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