Unable to fill vector inside structure

I am new to C ++, so bear with me.

I created a structure that looks like this:

struct node{ double startPoint; double endPoint; vector<node*> children; void addChild(node *aNode){ children.push_back(aNode); } void addPoints(double start, double end){ startPoint = start; endPoint = end; } }; 

Down my program, I have the following:

 vector<node*> data; .... node *temp = (node*)malloc(sizeof(node)); temp->addPoints(lexical_cast<double>(numbers[0]), lexical_cast<double>(numbers[1])); data[index]->addChild(temp); 

where "Index" is the index of vector data. lexical_cast takes these numbers from a string to a doubling.

Everything works up to the addChild(temp) .

The terminal spat out:

 First-chance exception at 0x585b31ea (msvcr90d.dll) in Tree.exe: 0xC0000005: Access violation reading location 0xcdcdcdc1. Unhandled exception at 0x585b31ea (msvcr90d.dll) in Tree.exe: 0xC0000005: Access violation reading location 0xcdcdcdc1. 

But I have no idea how to deal with this.

+4
source share
3 answers

malloc allocates some space, but does not put anything into it. It works great for structures with flat old data (or trivially initialized classes), and in C everything you have.

In C ++, you have classes, such as std::vector among others, that must be built correctly in order to set some invariants. This is done using a direct declaration for objects with automatic storage duration, but for objects with dynamic allocation, you need to use new instead of malloc .

For instance,

 std::vector<int> global; // (1) void foo() { std::vector<int> local; // (2) std::vector<int> *bad = malloc(sizeof(*bad)); // (3) std::vector<int> *good = new std::vector<int>; // (4) std::unique_ptr<std::vector<int>> better(new std::vector<int>); (5) } 
  • excellent - this global is initialized (by which I mean that the constructor is called) automatically
  • excellent - this local variable is also automatically created and destroyed properly as soon as foo exits
  • you cannot use bad for anything because any method you call assumes the constructor is already running and it is not
    • ok, you cannot use bad for anything without explicitly building it using the new placement. You should not do this, but this is only appropriate when you are doing smart or complex things with custom allocation.
  • This is normal (but note that you must remove it manually - foo has a memory leak)
  • it's better - you do not need to clean it manually

Now notice that your node class also has a constructor. In this case, it is automatically generated and does nothing but call the vector constructor. However, you need it to be called, which means using new to dynamically highlight the node .

So your program should probably be more like:

 std::vector<std::unique_ptr<node>> data; ... std::unique_pre<node> temp(new node); temp->addPoints(...); data[index]->addChild(temp); 

Note. I assume that data[index] is valid (I see that from addChild you know how to fill the vector already), and that the single-owner model implemented with unique_ptr is appropriate.

+2
source

As for the code that I see, you never add any nodes to the data array

 data.push_back(something); 

Thus, access to data[index] will be from the allocated memory of the array. He will not complain until you try to install memory in this block (through addChild tries to insert an element into the children array).

+1
source
  • I would recommend you store node instead of node* in your vector so that you don't have to manage memory yourself.
  • it is C ++, so you do not need malloc space for node, you can use the new one like this:
    Node * n = new Node();

  • The new is much better because it calls the constructor and allocates space, while malloc just does the latter.


You did not specify most of your code, but I would restructure the node class as follows.

 struct node{ double startPoint; double endPoint; vector<node> children; node(){} //add default constrcutor void addChild(node aNode){ children.push_back(aNode); } node & operator=(const node & n) { startPoint = n.startPoint; endPoint = n.endPoint; return *this; } node(double start, double end): startPoint(start),endPoint(end){ } //in c++ you have constructors which this should have been in the first place //constructors are used for initializing objects }; 
  • this is better since you cannot pass add child nullptr , avoiding a lot of problems in your code. You also have a constructor. Now you can add a node like this.

node temp(start,end); data[index]=temp;

  • Now you have a constructor that should have addPoints
  • I also made an assignment operator

Using a coding style in which you allocate memory on the stack and not use new is called RAII and is an important method of learning C ++ and creating a safe exception code, this is the main reason I don't protect node*

0
source

Source: https://habr.com/ru/post/1495830/


All Articles