Initialize array of structs in C++ - c++

I have struct Node in my code defined like this:
struct Node {
Node() : prev(0), left(0), right(0) {}
Node* prev;
Node* left;
Node* right;
char val;
};
I initialize array of Node structer objects like that:
Node** pool = new Node*[10000000];
I thought it will create Node structure objects using defoult constructor, but in fact the arrays seems to be empty. Is there any EFFICIENT way to create immidiately array of 'empty' objects?

You should be using std::vector<>; there is very little reason to use new in C++.
auto pool = std::vector<Node>(10000000);
(Your original code is creating Node*s, not Nodes.)
If for some reason you don't want to use vector, you could use std::unique_ptr<>. That code would be
std::unique_ptr<Node[]> pool(new Node[10000000]);
but you really should use vector.
Also, you can simplify and improve Node:
struct Node final {
Node* prev = nullptr;
Node* left = nullptr;
Node* right = nullptr;
char val = '\0';
Node(const Node&) = delete;
Node& operator(const Node&) = delete;
};

If you are constructing an ast/asg and you do not need linear data structures, you may consider still bulk allocating stuff with an ::std::vector<>, which will potentially give you cache locality.
You can still link individual Node objects via the pointers in your struct. If you then use indices instead of pointers, you can even resize your vector whenever you run out of available objects in your pool.

Node** pool = new Node*[10000000];
constructs an array of Node* rather than Node. What you are looking for is,
Node* pool = new Node[10000000];
which constructs an array of Node. If you actually want an array of Node* then the appropriate initialisation is,
int nObjects = 10000000;
Node** pool = new Node[nObjects];
for(auto i = 0; i < nObjects; ++i) {
pool[i] = new Node();
}
As others have said you likely do not want to use new or C-style arrays if you can avoid it.

Related

How can I delete the Error when creating pointers on C++? I this case I have to use raw pointers

I'm trying to make a linked list with a pointer to a template class called Node:
template <typename T>
class llnode
{
public:
T key;
llnode<T> *prev, *next;
llnode()
{
};
llnode(const T &k, llnode<T> *w = NULL, llnode<T> *y = NULL) : key(k), prev(w), next(y){};
~llnode()
{
delete this;
}
};
But, when I run the program this code in the main function
llnode<int> *node;
node->key = 6;
llnode<int> *node1;
node->key = 2;
I get the error message:
403 cygwin_exception::open_stackdumpfile: Dumping stack trace to "NAME OF MY EXE".exe.stackdump
How can I create more nodes without getting the error?
It happens when I have 2 nodes created, but when I have 1 it does it right.
When you use them in main your pointers are not initializated. This ends in Undefined Behavior.
Do this:
llnode<int> *node = new llnode<int>;
node->key = 6;
llnode<int> *node1 = new llnode<int>;
node->key = 2;
Also note that calling delete this; in the destructor causes an infinite loop (More info here). Remove the destructor and free the space manually or better use a Smart Pointers or RAII approach.
First, for
llnode<int> *node;
node->key = 6;
llnode<int> *node1;
node->key = 2;
your problem is that node is an uninitialized pointer. You should always initialize your pointers (or better, use smart pointers like unique_ptr). Try:
std::unique_ptr<llnode<int>> node = std::make_unique<llnode<int>>();
node->key = 6;
std::unique_ptr<llnode<int>> node1 = std::make_unique<llnode<int>>();
node->key = 2;
or better:
auto node = std::make_unique<llnode<int>>(6);
auto node1 = std::make_unique<llnode<int>>(2);
In general, this is very C-like C++. Raw pointers are hard to use correctly, particularly when it comes to exception safety. For that reason, I make an effort to never write new or delete ever. (There are places, but really, you want to avoid them.)
You can use std::unique_ptr to do cleanup (and initialization) for you. You can also default raw pointers to nullptr.
In C++11 and beyond, don't use NULL, use nullptr, it's safer.
Consider something like this:
#include <memory>
template <typename T>
class llnode
{
public:
T key;
llnode<T>* prev = nullptr; // Raw pointer back
std::unique_ptr<llnode<T>> next; // List owns it tail.
llnode(const T &k = {},
llnode<T> *w = nullptr,
std::unique_ptr<llnode<T>> y = nullptr)
: key(k), prev(w), next(std::move(y)) {}
};
When this node is deleted, the node pointed to by next (if next != nullptr) will also be deleted for you.
Often a doubly-linked linked list will have a separate type that hides the nodes from the user, maintaining access to the front and back. Then you can provide standard operations such as list<T>.push_back(const T&).

Passing a linked list without memory leak in C++

In many occasions, we need to modify a linked list drastically so we will sometimes create another linked list and pass it to the old one. For example,
struct node { //let's say we have a linked list storing integers
int data;
node* next;
};
and suppose we already have a linked list storing integers 1,2,3.
node* head; //suppose we already store 1,2,3 in this linked list
node* new_head ; //suppose we make a temporary linked list storing 4,5,6,7
head = new_head; //modifying the original linked list
My Question
If I delete head (the old linked list) before the assignment then the whole program will crash.
Conversely, if I do not delete it, then there will be a memory leak.
Therefore, I am looking for a way to modify the linked list without memory leak.
My attempt
I tried to make a helper function similar to strcpy to do my work.
void passing_node(node*& head1, node* head2){ //copy head2 and paste to head1
node* ptr1 = head1;
for (node* ptr2 = head; ptr2 != nullptr; ptr2 = ptr2->next)
{
if (ptr1 == nullptr){
ptr1 = new node;
}
ptr1->data = ptr2->data;
ptr1 = ptr1->next;
}
}
// note that we assume that the linked list head2 is always longer than head1.
However, I still got a crash in the program and I cannot think of any other way to modify this. Any help would be appreciated.
Easier way to avoid memory leak is to avoid raw owning pointers.
You might use std::unique_ptr (or rewrite your own version):
struct node {
int data = 0;
std::unique_ptr<node> next;
};
You can move nodes.
You can no longer copy nodes (with possible double free issue).
so deep_copy might look like:
std::unique_ptr<Node> deep_copy(const Node* node)
{
if (node == nullptr) return nullptr;
auto res = std::make_unique<Node>();
res->data = node->data;
res->next = deep_copy(node->next.get());
return res;
}
I would suggest preallocating the linked list so it's easy to delete every node in one call. The nodes would then just reference somewhere inside this preallocated memory. For example:
struct Node
{
int value;
Node* next;
};
struct LinkedList
{
Node* elements;
Node* first;
Node* last;
Node* free_list;
LinkedList(size_t size)
{
first = nullptr;
last = nullptr;
elements = new Node[size]{0};
free_list = elements;
for (size_t i = 0; i < size-1; ++i)
free_list[i].next = &free_list[i+1];
free_list[count-1].next = nullptr;
}
~LinkedList()
{
delete[] elements;
}
void Add(int value)
{
if (free_list == nullptr)
// Reallocate or raise error.
// Take node from free_list and update free_list to
// point to the next node in its list.
// Update last node to the new node.
// Update the first node if it's the first to be added.
}
void Free(Node* node)
{
// Search for the node and update the previous and
// next's pointers.
// Update first or last if the node is either of them.
// Add the node to the last place in the free_list
}
};
From here you'll have many strategies to add or remove nodes. As long as you make sure to only add nodes to the allocated elements array, you'll never have any memory leak. Before adding, you must check if the array have the capacity to add one more node. If it doesn't, you either have to raise an error, or reallocate a new the LinkedList, copy over all values, and delete the old one.
It becomes a bit more complicated when the array becomes fragmented. You can use a 'free list' to keep track of the deleted nodes. Basically, a LinkedList of all nodes that are deleted.
Just take notice that my code is incomplete. The basic approach is to create an allocator of some sort from which you can allocate a bulk, use segments of it, and then delete in bulk.

C++ how should I structure a tree

I am currently working on a large data tree. I need to navigate the tree, return a subnode and change its value.
class Node {
short value;
std::vector<Node> children;
Node walk(int step) {
return children[step];
}
}
Will the return of the Walk function create a copy of the child Node or do I have to return a pointer? How should I Link the Nodes?
also another question:
what's the difference between these two and which should I use to create new nodes:
Node newNode;
// or
Node newNode = *new Node();
Edit
I tried std::vector<Node*> children; but this lead to memory leaks when deleting. Would Node& walk(int step) work too without using pointers?
To prevent memory leaks and keep your code clean, you can use shared pointers. Return weak pointer from walk function. We must return the weak pointer so as not to make the client the owner of a particular node.
#include<memory>
#include<vector>
class Node;
using NodePtr = std::shared_ptr<Node>;
using NodeWPtr = std::weak_ptr<Node>;
class Node {
short value;
std::vector<NodePtr> children;
NodeWPtr walk(int step) {
//Your Algorithm.
return children[step];
}
};
Node newNode = *new Node(); creates a Node on the heap and then copies it to a node on the stack. This however, has memory leak and it does not do anything significantly different than just creating a node directly on the stack.
Node newNode; creates Node object on the stack. I would suggest you use this as it directly describes your intent.
Some people have suggested the use of std::unique_ptr instead of std::shared_ptr because std::shared_ptr has a large overhead. However, if we do use std::unique_ptr, we would have to return an std::observer_ptr from the walk function which is not fully implemented in the latest c++ compilers as far as I know.
EDIT
The following 2 class designs are noteworthy of consideration according to the discussions in the comments.
//Without storing any pointers in the vector
class Node {
short value;
std::vector<Node> children;
Node* walk(int step) {
//Your Algorithm.
return &children[step];
}
};
or
//Using unique_ptr
class Node;
using NodePtr = std::unique_ptr<Node>;
class Node {
short value;
std::vector<NodePtr> children;
Node* walk(int step) {
//Your Algorithm.
return children[step].get();
}
};

How to delete a binary search tree from memory?

I have a BST which is a linked list in C++. How would I delete the whole thing from memory? Would it be done from a class function?
Just delete the children:
struct TreeNode {
TreeNode *l, *r, *parent;
Data d;
TreeNode( TreeNode *p ) { l = nullptr; r = nullptr; parent = p; }
TreeNode( TreeNode const & ) = delete;
~TreeNode() {
delete l; // delete does nothing if ptr is 0
delete r; // or recurses if there's an object
}
};
or if you're using unique_ptr or some such, that's not even needed:
struct TreeNode {
unique_ptr< TreeNode > l, r;
TreeNode *parent;
Data d;
TreeNode( TreeNode *p ) { l = nullptr; r = nullptr; parent = p; }
TreeNode( TreeNode const & ) = delete;
~TreeNode() = default;
};
If you have access to the linked list itself, it's a piece of cake:
// Making liberal assumptions about the kind of naming / coding conventions that might have been used...
ListNode *currentNode = rootNode;
while(currentNode != NULL)
{
ListNode *nextNode = currentNode->Next;
delete currentNode;
currentNode = nextNode;
}
rootNode = NULL;
If this is a custom implemention of a BST, then this may well be how it works internally, if it has tied itself to a particular data structure.
If you don't have access to the internals, then Potatoswatter's answer should be spot on. Assuming the BST is setup as they suggest, then simply deleting the root node should automatically delete all the allocated memory as each parent down the tree will delete its children.
If you are asking how to go about iterating across a binary tree manually, then you would do the following recursive step:
void DeleteChildren(BSTNode *node)
{
// Recurse left down the tree...
if(node->HasLeftChild()) DeleteChildren(node->GetLeftChild());
// Recurse right down the tree...
if(node->HasRightChild()) DeleteChildren(node->GetRightChild());
// Clean up the data at this node.
node->ClearData(); // assume deletes internal data
// Free memory used by the node itself.
delete node;
}
// Call this from external code.
DeleteChildren(rootNode);
I hope I've not missed the point here and that something of this helps.
Perform a post-order traversal of the tree (i.e. visiting children before parents), and delete each node as you visit it.
Whether or not this has anything to do with classes depends entirely on your implementation.
With the limited information provided ....
If you allocated the nodes with new or malloc (or related functions) than you need to traverse over all the nodes and free or delete them.
An alternative is to put shared_ptr's (and weak_ptr's to kill cyclics) in your allocations -- provided you do it correctly you won't have to free the nodes manually
If you used a quality implementation that you picked up on the internet than provided the classes don't leak, you don't have to worry about anything.
Use smart pointers and forget about it.

C++ linked list memory management

I'm attempting to craft my own basic singly linked list in C++ as a learning exercise, and I'm encountering some difficulty in the memory management department. As it stands I have...
A 'Node' class:
class Node
{
public:
char *value;
Node *next;
Node();
~Node();
};
Node::Node()
{
}
Node::~Node()
{
delete[] value;
}
And then my list (I've omitted certain method calls for brevity):
class LinkedList
{
private:
Node *head;
public:
LinkedList();
~LinkedList();
void Add(char **x);
};
LinkedList::LinkedList()
{
head = 0;
}
LinkedList::~LinkedList()
{
Node *temp;
Node *current = head;
while(current)
{
temp = current;
current = current->next;
delete temp;
}
}
void LinkedList::Add(char **x)
{
Node *nodeToAdd = new Node();
nodeToAdd->value = *x;
nodeToAdd->next = NULL;
Node *current = head;
if(!head)
{
head = nodeToAdd;
return;
}
while(current->next)
{
current = current->next;
}
current->next = nodeToAdd;
}
I'm attempting to use this code as follows (again I've omitted things for brevity):
int main()
{
LinkedList *list = new LinkedList();
char *alpha = "alpha";
char *beta = "beta";
char *charlie = "charlie";
char *delta = "delta";
char *echo = "echo";
list->Add(&alpha);
list->Add(&beta);
list->Add(&charlie);
list->Add(&delta);
list->Add(&echo);
delete list;
}
The last call in main to delete the list produces an error:
Debug Assertion Failed! Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
What am I doing wrong here?
The data pointed to by the various Node::value aren't dynamically allocated, so you shouldn't delete them. Applying the concept of "ownership", nodes should either make their own copies of data, which they own and can delete, or nodes don't own data, so they shouldn't be responsible for deleting it.
You can also implement multiple ownership using reference counting, like Objective-C does (see Objective-C Memory Management Rules for more info) but you have to be careful to avoid ownership cycles. You often find some type of reference counting in third-party smart pointers, such as Boost's smart_ptr library. Since you're doing this for the learning experience, it may make more sense to roll your own than use a library. Of course, you could also use a library for now, letting you focus on whatever you're trying to learn.
One day a student came to Moon and said: “I understand how to make a better garbage collector. We must keep a reference count of the pointers to each cons.”
Moon patiently told the student the following story:
“One day a student came to Moon and said: ‘I understand how to make a better garbage collector...
you are trying to release the memory which is not allocated on heap.
char *alpha = "alpha"; --- not allocated on heap
calling delete[]in Node destructor would lead to heap corruption.
Some points:
1) initialize pointers properly in the constructor:
Node::Node():value(NULL),next(NULL)
{
}
2) Take a ownership of value.
Allocate the memory on heap and copy
the contents
You shouldn't release a pointer use delete[]/delete if it's not created by new operator. There are some actions under the hood for the delete[] operation, like releasing/reclaiming marked memory from a managed pool. Since your pointer doesn't belong to these stuff, there will be a problem. IMHO, the underlying delete[] code is the _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) stuff.
The problem is that you're assuming that you can delete the data inside node, but you're passing in pointers to string literals instead, which you can't delete.
If you're assuming that the Node object controls the lifetime of the data inside it, your Node constructor or the Add function in LinkedList will have to make a copy of the data that it is being passed.
In your destructor, you are trying to array delete (delete [ ]) a static string. You have change your Add function to reserve the string and copy it first. See the code below.
However, if I were you and fairly new to memory management, I'd really use something like CString instead of a raw "char *" as it's much easier to deal with.
void LinkedList::Add(const char *x)
{
Node *nodeToAdd = new Node();
int len=strlen(x);
nodeToAdd->value = new char [len+1]; // room for string + terminating 0
strcpy(nodeToAdd->value,x);
nodeToAdd->next = NULL;
Node *current = head;
if(!head)
{
head = nodeToAdd;
return;
}
while(current->next)
{
current = current->next;
}
current->next = nodeToAdd;
}
value and next in Node class doesn't have memory allocated. You should allocate memory in Node's constructor.