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.