简体   繁体   中英

How to fix 'Segmentation fault' error in c++

I'm trying to learn how to use the gdb debugger to fix this sample code. When stepping through the debugger, I can see that the line 'mylist[i]->val = i;'is throwing the segmentation fault.

I think I understand what a segmentation fault is, but I don't understand how this line could be causing it. Do I need to allocate memory for the mylist vector? How would I do that? I thought that the vector was already initialized and ready in main(), but I'm not really sure.

I have tried using 'new' for each node in the mylist vector but that gave me a compile error.

node* mylist[i] = new node; //what I tried
mylist[i]->val = i; 
mylist[i]->next = NULL;   

//error message
error: array must be initialized with a brace-enclosed initializer
node* mylist[i] = new node;

My code

class node
{
public:
    int val;
    node* next;
};

void create_LL(vector<node*>& mylist, int node_num)
{
    mylist.assign(node_num, NULL);

//create a set of nodes
    for (int i = 0; i < node_num; i++)
    {
        mylist[i]->val = i; //error happens here
        mylist[i]->next = NULL;
    }

... (relevant section of main() below)

int main(int argc, char ** argv)
{
    const int NODE_NUM = 3;
    vector<node*> mylist;
    create_LL(mylist, NODE_NUM);

The actual error shown is "Segmentation fault (core dumped)"

When I print mylist right before the error line it shows

$1 = std::vector of length 3, capacity 3 = {0x0, 0x0, 0x0}

I am still learning c++ so I might be missing something really basic. I would really appreciate any help. Thanks!

For starters, it's better if you hide variables inside a class . If you're not going to, the convention is to use a struct . It's also good practice to provide some constructor in that case, and maybe with default values:

class node
{
    int val;
    node* next;
public:
    node(int v= 0, node* n= nullptr) : val(v), next(n) {}
};

Note the use of nullptr instead of NULL . Using the latter is a bad practice in c++.

The problem is that you can't use positions on a std::vector if they have not been allocated. When you do mylist[i]->val = i; you're in the lands of undefined behaviour.

You need first to push_back() or emplace_back() into a std::vector . So it's size() grows as it puts your data at the end (the back ) of the vector . You could also use other methods, like reserve() . While push_back() pushes node* elements on your list, emplace_back() would construct them in place with no copy (no difference with raw pointers, but you can use a vector<node> instead of vector<node*> which is more straightforward.

// create a set of nodes
void create_LL(vector<node>& mylist, int node_num)
{
    for (int i = 0; i < node_num; i++) {
        mylist.emplace_back(i, nullptr); // calls node::node(i, nullptr) and inserts it at the end of the vector
    }

or

// create a set of nodes
void create_LL(vector<node*>& mylist, int node_num)
{
    for (int i = 0; i < node_num; i++) {
        mylist.emplace_back(new node(i, nullptr));
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM