0

I am trying to understand the passing of pointers using reference, and I have a code which is below

// { Driver Code Starts
#include <bits/stdc++.h>

using namespace std;

 // } Driver Code Ends
//User function template for C++

class Node{
       
    public:
        int val;
        Node *left,*right;
        int count;
        
        Node(int key,int c){
            this->val=key;
            this->count=c;
            this->left=this->right=NULL;
        }
};
    
class NodeInsert{
public:
    int insert(Node*& node,int key,int countSmaller){

        if(node==NULL){
            node=new Node(key,0);
            return countSmaller;
        }
        
        if(key<node->val){
            node->count++;
            return insert(node->left,key,countSmaller);
        }
        else{
            if(key>node->val){
                return node->count+insert(node->right,key,countSmaller+1);
            }
        }
    }
    
    void temp(){
    cout<<"hello world"<<"\n";
    }
};

class Solution{
public: 
    vector<int> constructLowerArray(int *arr, int n) {

        vector<int> ans;
        Node *root=NULL;
        
        NodeInsert *n_ins=new NodeInsert();
        for(int i=n-1;i>=0;i--){
            ans[i]=n_ins->insert(root,arr[i],ans[i]);
        }

        
        return ans;
    }
};
    

    


// { Driver Code Starts.

int main() {
    int n=4;
    int arr[n]={12,3,2,1};
    Solution *ob=new Solution();
    auto ans = ob->constructLowerArray(arr, n);
        
        for (auto x : ans) {
            cout << x << " ";
        }
        cout << "\n";
    return 0;
}

I executed the above code and got segmentation fault and to find out which line is causing the segmentation fault I had to follow the below steps:

compile the code using

a) gcc -g tree.cpp -lstdc++

b) gdb a.exe core

then press r

and it returned the line number which causing the segmentation fault

GNU gdb (GDB) 7.6.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from C:\workarea\cpp\a.exe...done.
C:\workarea\cpp/core: No such file or directory.
(gdb) r
Starting program: C:\workarea\cpp/a.exe
[New Thread 10728.0x3614]
[New Thread 10728.0x33ec]
[New Thread 10728.0x5ae8]
[New Thread 10728.0x724]

Program received signal SIGSEGV, Segmentation fault.
0x00407c7e in Solution::constructLowerArray (this=0x821818, arr=0x63feb0, n=4, root=@0x63fee4: 0x0) at tree.cpp:57
57                      ans[i]=n_ins->insert(root,arr[i],ans[i]);

the line 57 in my code is

ans[i]=n_ins->insert(root,arr[i],ans[i]);

the gcc version which I am using is

gcc --version
gcc (MinGW.org GCC-6.3.0-1) 6.3.0
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

and using the below links

  1. C++ initial value of reference to non-const must be an lvalue

  2. Error when passing a pointer by reference

I came to know that in c++ we cannot assign references to temporary variables

But I couldn't understand what's the temporary variable in my code Is it root?

However the below code (copied from geeksforgeeks) runs fine without any issues

#include<bits/stdc++.h>
using namespace std;

// BST node structure
class Node{
    
public:
    int val;
    int count;
    Node* left;
    Node* right;
    
    // Constructor
    Node(int num1, int num2)
    {
        this->val = num1;
        this->count = num2;
        this->left = this->right = NULL;
    }
};

// Function to addNode and find the smaller
// elements on the right side
int addNode(Node*& root, int value,
                        int countSmaller)
{
    
    // Base case
    if (root == NULL)
    {
        root = new Node(value, 0);
        return countSmaller;
    }
    if (root->val < value)
    {
        return root->count +
    addNode(root->right,
            value,
            countSmaller + 1);
    }
    else
    {
        root->count++;
        return addNode(root->left, value,
                    countSmaller);
    }
}

// Driver code
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int data[] = { 10, 6, 15, 20, 30, 5, 7 };
    int size = sizeof(data) / sizeof(data[0]);
    int ans[size] = {0};

    Node* root = NULL;
    
    for(int i = size - 1; i >= 0; i--)
    {
        ans[i] = addNode(root, data[i], 0);
    }

    for(int i = 0; i < size; i++)
        cout << ans[i] << " ";

    return 0;
}

I am unable to find the difference between my code and the code from geeksforgeeks. What exactly is causing the segmentation fault in my code?

E_net4
  • 27,810
  • 13
  • 101
  • 139
Akhil
  • 391
  • 3
  • 20
  • Whatever source you use to learn C++ I suggest you throw it away, and instead get [some good books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) and take some classes. The GCC C++ front-end program is named `g++`, and [don't include ``](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h). And a good C++ resource should also tell you that vectors start out *empty* and any and all indexing into them will lead to *undefined behavior* (and possible crashes like yours). – Some programmer dude Jul 17 '21 at 16:16
  • `vector ans;` creates an empty vector. `ans[i] = n_ins->insert(root, arr[i], ans[i]);` indexes into the empty vector out of range. Also: `'NodeInsert::insert': not all control paths return a value` – Retired Ninja Jul 17 '21 at 16:18
  • @Someprogrammerdude ,I am learning from this link https://www.geeksforgeeks.org/how-to-find-segmentation-error-in-c-c-using-gdb/,well technically I am learning from geeksforgeeks , I got the resources from the link you pasted and will start using that to learn , anyways thanks a ton for helping me ,you saved my time – Akhil Jul 17 '21 at 16:19
  • @RetiredNinja ,thanks a ton to you as well for helping me – Akhil Jul 17 '21 at 16:26
  • Try book C++20 by Rainer Grimm. – Swift - Friday Pie Jul 17 '21 at 16:32
  • Simplification tips for creating a [mre]: I'll focus on the line at which the segmentation fault occurred: `ans[i]=n_ins->insert(root,arr[i],ans[i]);`. This line occurs in a loop; remove the loop. Does the segmentation fault occur in the first iteration? (Yes.) Since we are interested in the segmentation fault instead of in constructing the lower array, drop the loop, replacing it with the line from the first iteration, `ans[n-1]=n_ins->insert(root,arr[n-1],ans[n-1]);`. Break this line into pieces to see which one is problematic, for example isolate the parameters as in `auto& p2 = ans[n-1];`. – JaMiT Jul 17 '21 at 23:22

0 Answers0