segmentation fault when using pointer to pointer C++ - c++

I have been trying to use pointer to pointer to perform action something similar to inorder traversal in tree. here is my code
struct node {
char c = '\0';
int freq = 0;
node *left = NULL;
node *right = NULL;
string code = "";
};
void appendones(node **n) {
if ((*n) == NULL)
;
else {
(*n)->code += "1";
appendones(&(*n)->left);
appendones(&(*n)->right);
}
}
void combinenodes(node *a, node *b, node **n) {
appendones(&a);
appendones(&b);
//(*n)=newNode('\0',a->freq+b->freq);
(*n)->c = '\0';
(*n)->freq = a->freq + b->freq;
(*n)->left = a;
(*n)->right = b;
}
int main() {
N = input();
priority_queue<node, vector<node *>, compareNodefreq> nodefreq; // function object
for (int i = 0; i < N; i++) {
char s;
int freq;
cin >> s >> freq;
node *n = newNode(s, freq);
nodefreq.push(n);
}
// printheap(nodefreq);
// perform combining nodes based on frequencies
while (nodefreq.size() > 1) {
node *a = nodefreq.top();
nodefreq.pop();
node *b = nodefreq.top();
nodefreq.pop();
node *n;
combinenodes(a, b, &n);
nodefreq.push(n);
}
}
I get segmentation fault in (*n)->code+="1"; for appendone().
I am not able to figure out the error. My understanding is that I am passing
the pointer by reference and performing the appendzero() and appendone(),
so I guess there is no error in that part. Also my a and b in
combinenodes() cannot be null because I am popping from the stack.
Could you help me figure out?

Oh, I see it. In main()'s while loop, n is pushed and used later, but is invalid because the node object itself is never allocated in combinenodes() (currently commented out). The pointer value, then, is undefined, but in this case, turning out to be non-zero, defeating the safety check.

Related

How can I assign an int array to linkedlist struct?

Hi I'm a beginner at c++ and I'm having trouble solving this issue. I have a linkedlist of nodes and the node contains data of int array and a pointer pointing to the next node.
struct node {
unsigned int numbers[6];
node* next;
};
I also have a class:
private:
ticket* ticketListHead;
ticket* ticketListTail;
and in a public method:
public:
void newNode() {
int arr[6];
for(int i = 0; i < 6; ++i) {
arr[i] = ( std::rand() % 49 ) + 1;
}
node *temp = new node;
temp->numbers=arr;
temp->next=NULL;
}
The problem I believe is with the temp->numbers=arr line as I believe arrays cannot be assigned like that in C++. I'm not sure how to solve the problem in this case and I've tried looking online. Some help would be appreciated!
You're correct about your suspicion that you cannot assign arrays. You could instead use a wrapper type that allows assignment and define
using array = std::array<unsigned,6>; // convenient short hand
struct node {
array numbers;
node* next = nullptr; // ensure next defaults to null
};
when your newNode() method may look like
node* newNode() {
array arr;
for(auto&x: arr)
x = ( std::rand() % 49 ) + 1; // std::rand() cannot be recommended
auto temp = new node;
temp->numbers = arr;
return temp;
}
but you can avoid the temporary object arr altogether by directly writing into the new node's data:
node* newNode() {
auto temp = new node;
for(auto&x: temp->numbers)
x = ( std::rand() % 49 ) + 1; // std::rand() cannot be recommended
return temp;
}
Btw, you shouldn't use std::rand() (see this post and this presentation for reasons why). Instead, use the methods provided by <random>, when your code becomes (see also this answer)
template<typename Generator>
node* newNode(Generator&rng) {
std::uniform_int_distribution<unsigned> uni(1,49);
auto temp = new node;
for(auto&x: temp->numbers)
x = uni(rng); // guaranteed unbiased in [1,49] inclusive
return temp;
}
Welcome to C++, it's awesome that you're taking your first steps into a brighter world! What you'll want to look into are C++ container classes, they'll get you out of the business of managing memory on your own. The closest to your code is std::list and std::vector. I'll neglect random number seeding, that's a complex topic better discussed elsewhere.
#include <vector>
#include <list>
#include <iostream>
#include <random>
#include <limits>
using namespace std;
struct node {
node() : num(6) {
numbers.reserve(num);
for (int i = 0; i < num; ++i)
numbers.push_back(random() % numeric_limits<int>::max());
}
vector<int> numbers;
const int num;
};
int main(int argc, char** argv) {
list<node> nodes;
nodes.push_back(node()); // this replaces your newNode function
nodes.push_back(node()); // another call to better illustrate
for (auto mynode : nodes) {
for (auto mynum : mynode.numbers)
cout << mynum << " ";
cout << endl;
}
}
// Change node struct to this
struct node{
unsigned int *numbers;
node* next;
};
/*
Remember that normal arrays are
implemented through pointers. So you
can use a pointer named numbers in
your node struct and it would behave
as an array.
*/
// Change newNode() to this
void newNode() {
int * arr = new int[6]; //Dynamic memory allocation
for(int i = 0; i < 6; ++i)
{
arr[i] = ( std::rand() % 49 ) + 1;
}
node *temp = new node;
temp->numbers = arr;
temp->next = NULL;
}
U got it ?

a loop that prints all the items (no matter how long the chain is) *pointers

The following is a basic code and I was wondering what was the basic way to write a loop on how to display the contents/data from the array of pointers. The top is a class with everything under public. Declaring a data of string followed by an array of pointers called next. In the main function, I'm declaring a few nodes and allocating memory to its followed by a string. A, B, and C. Towards the end of the code I'm connecting the pointers to each data and the last one C to NULL. And at the end, I'm having a bit of trouble writing or grasping the concept on how to write a loop to display it's contents, i.e Node1, Node2, Node3... Preferably a loop that'll display everything no matter the size.
#include <iostream>
using namespace std;
class node
{
public:
string data;
node * next;
};
int main()
{
node * A;
A = new node;
(*A).data = "node1";
node * B;
B = new node;
(*B).data = "node2";
node * C;
C = new node;
(*C).data = "node3";
(*A).next = B;
(*B).next = C;
(*C).next = NULL;
for(int i=0; *(next) != NULL; i++)
{
cout << *next[i[] << endl;
}
system("pause");
return 0;
}
use a temporary pointer that's initialized with the start of the node and use a while loop.
Node* tmp = A;
while (tmp) { // same as (tmp != NULL)
cout << tmp->data << endl;
tmp = tmp->next; // down the rabbit hole
}
Also, You could collapse the declaration of variables with assignment.
Node* A = new Node;
1.) remove for loop
printList(A);
void printList(node *first)
{
node *first = A;
while(first)
{
cout<<first->data<<endl;
}
}

I Am Having Issues with Passing Struct Pointers

I am issues with a homework assignment. We are working on binary trees and whenever I try to pass my head node to my insert() function the node is not being changed. This has lead me to believe that I am somehow not passing by reference, I just can't figure out where the mistake is, however. Thank you for any help in advance.
/*Linked List
**Code inspired by Linked List by Daniel Ross
**Code written by Collin Bardini
**Assignment 6
*/
#include <iostream>
using namespace std;
//Our node
struct node {
int data;
node* left; //lower
node* right; //greater
};
//function declarations
void insert(node * head, int);
void print_preorder(node * root);
void print_postorder(node * root);
void print_inorder(node * root);
int search(int data, node * root);
//main for testing the access functions
void main(void)
{
node* headA = 0;
node* headB = 0;
const size_t as = 7;
const size_t bs = 100;
int a[as] = {1,5,4,6,7,2,3};
int b[bs] = {118,119,158,166,163,123,108,116,117,184,165,137,141,111,138,122,109,194,143,183,178,173,139,
126,170,190,140,188,120,195,113,104,193,181,185,198,103,182,136,115,191,144,145,155,153,151,
112,129,199,135,146,157,176,159,196,121,105,131,154,107,110,175,187,134,132,179,133,102,172,
106,177,171,156,168,161,149,124,189,167,174,147,148,197,160,130,164,152,142,162,150,186,169,
127,114,192,180,101,125,128,100 };
for (int i = 0; i < as; i++)
insert(headA, a[i]);
for (int i = 0; i < bs; i++)
insert(headB, b[i]);
print_preorder(headA);
cout << "search 196: " << search(196, headB) << endl <<
"search 137: " << search(137, headB) << endl <<
"search 102: " << search(102, headB) << endl <<
"search 190: " << search(190, headB) << endl;
}
// creates a new node and inserts it in the correct location in the tree
void insert(node * head, int d)
{
//make a new node
node *p = new node;
p->right = 0;
p->left = 0;
p->data = d;
if (head == 0) //list is empty
head = p;
else //append to tail end
{
node* c1 = head;
node* c2 = head;
while (c1)
{
if (d > c1->data)
{
c2 = c1;
c1 = c1->right;
}
else
{
c2 = c1;
c1 = c1->left;
}
}
if (d > c2->data)
c2->right = p;
else
c2->left = p;
}
}
Short answer: see my answer to this identical question and use double pointers in the insert() function.
Regarding the "pass-by-reference" part of the question, well it depends on what exactly you mean by these words. You are passing the node by reference, true, but you're passing the pointer to the node by value. Remember that pointer is just another variable holding a non-negative integer value (overly simplified, but still true).
Long answer: the modifying functions should use either double pointers or references to pointers. The reason is that, in a function definition like void insert(node * head, int d) { /*...*/ }, the pointer itself is passed by value. That is, a temporary copy of the original pointer is created, and modified inside the function. The actual pointer remains unchanged. I.e., in these lines:
// definition
if (head == 0) //list is empty
head = p;
// client code
for (int i = 0; i < as; i++)
insert(headA, a[i]);
The temporary local variable head is modified, not the headA variable that you pass to the function. See the linked question where I posted a schematics of what happens with the pointer values in this situation.
You can change to e.g. double pointers like so:
void insert(node ** head, int d) {
// snip...
if (*head == 0) //list is empty
*head = p;
Or pass the pointer by reference.
Note: for read-only functions, such as print...(), you don't need to use a double pointer or any other pass-by-reference mechanism.

Segmentation fault in creating Linked list

In this particular question I am trying to find the segmentation fault which is occurring. I know there is an error while creating a linked list of individual digits of K.
struct Node
{
int data;
struct Node *next;
};
int n1 = 0;
int n2 = 0;
int k = 1;
int calc(Node *h)
{
int sum=0;
for( ; h != NULL ; h = h->next)
sum=(sum*10)+h->data;
return sum;
}
Node* Lists(Node *headA, Node* headB)
{
n1 = calc(headA);
n2 = calc(headB);
int k = n1 + n2;
Node *temp;
temp->data=k%10;
while(k>0)
{
k=k/10;
Node *t1=new Node;
t1->data=k%10;
t1->next=temp;
temp=t1;
}
return temp;
}
The error resides in the following code:
Node *temp;
temp->data = k % 10;
Specifically, temp is declared to be a pointer that points to a Node struct, but it is never given a valid location in memory to point to, so it contains a garbage address that most likely refers to some non-writeable region.
If you wanted to fix this, you would first allocate a region for your variable, like this:
Node *temp = new Node;
and then mark it as released (by calling delete on it) later on when you were done with it. I would also recommend better formatting your code, as it's not exactly convenient to read from the viewer's perspective.

Undefined action? Program prints out different values one after the other

I didn't quite know how to describe the question -and whether there is any name for my error.
When i run the programme type some number e.g. 5 the tree.root->pocz is first 1 and later the weird number. Anyone know what's going on and how to repair it?
struct Node
{
int pocz;
int kon;
Node *left, *right, *up;
};
class AVL{
public:
Node *root;
void initiate(){
root = NULL;
}
bool insertNode(int poczPrz, int konPrz);
};
AVL tree;
//part of AVL insert function
bool AVL::insertNode(int poczPrz, int konPrz){
Node w;
w.pocz = poczPrz;
w.kon = konPrz;
Node *n = &w;
Node *x = tree.root;
Node *y, *z;
y = n->left = n->right = NULL;
while(x){
if(x->pocz == n->pocz){
delete n;
return false;
}
y = x;
x = (n->pocz < x->pocz) ? x->left : x->right;
}
if(!(n->up = y)){
cout << "We leave the function here\n";
tree.root = n;
return true;
}
if(n->pocz < y->pocz) y->left = n;
else y->right = n;
}
int main()
{
int n; cin >> n;
tree.initiate();
tree.insertNode(1,n);
cout <<"root->pocz: "<< tree.root->pocz <<endl; //prints 1
cout <<"root->pocz: "<< tree.root->pocz <<endl; //now prints sth like 2306050
return 0;
}
The main problem is that n points to w which is a local variable in the function insert. At the end of the function insert, w gets deleted automatically. And the pointer that is in the tree points to an empty location. At your first cout instruction, by chance, nothing did overwrite over the previous memory location of w. Therefore it prints 1. That memory location is then over written by something else (from the cout call) and therefore it prints garbage.
Now the solution, use Node *n = new Node; instead of setting it to &w.
In insertNode your w object has automatic storage and n is a pointer to it. In the call to that function, it will assign tree.root = n;. After the function returns the object is destroyed and the pointer tree.root is left dangling (points to deallocated memory). After that, dereferencing the dangling pointer such as tree.root->pocz will have undefined behaviour. You can fix that by allocating the Node dynamically.