I have a std::unordered_map<char, Node*> inside my custom structure.
I want to initialize it with an empty map. Did I do something wrong?
I have tried 2 kinds of initialization, both of them give me same result.
The following statement:
newStructure->map = unordered_map<char, Node*>();
sometimes results in success and the size of this map is 0, which it should be. Most of the time, this would fail during the initialization, and the following error would be generated with no initialization of the map:
malloc: pointer being freed was not allocated
This would give me extreme huge size of the initial std::unordered_map. The size of the map could be 88029716824088.
How can I correctly initialize an empty std::unordered_map struct?
My structure is defined like this:
struct Node {
char letter;
unordered_map<char, Node*> next;
bool hasEnd;
static Node* init(char);
}
And, my initializer is defined like this:
Node* Node::init(char letter) {
Node *newNode = (Node*) malloc(sizeof(Node));
newNode->letter = letter;
newNode->hasEnd = false;
return newNode;
};
Sometimes, the size of the next would be very huge number.
You need to use new instead of malloc when creating C++ objects.
When you create a map it is already empty by default.
You can read more here: In what cases do I use malloc and/or new?
The actual failure and the strange map size happens because when you do this:
Node *newNode = (Node*) malloc(sizeof(Node));
You are saying that there struct Node at the address you got from malloc.
The problem is that the constructor for the unordered_map will not get called. And malloc is not required to return zeroed memory.
This means that internals of unordered_map will simply be whatever values are there in the memory returned by malloc. Also keep in mind that zeroes also might not be ok for correct initialization of unordered_map internals. It will only be correctly initialized if its constructor gets called.
This you a Node with a broken unordered_map member
Then when you do:
newStructure->map = unordered_map<char, Node*>();
The destructor for the unordered_map will get called, because you are actually replacing the unordered_map which you said is already there with a new one. Since the values in the memory you got from malloc might not be 0 and the unordered_map internals might contain a pointer to some memory that gets allocated when its constructor gets called, the destructor will try to deallocate some random value, causing the error you are seeing.
Related
Assume we have a List class with a data member called front which is a Node pointer. Below is a member function to display the members of a list (the calling object).
It has an error. Identify and describe the error in a few
words. Then correct the error.
void display ()
{
Node *temp= new Node;
temp=front;
while (temp!=NULL)
{
cout<<temp->data<<"\t";
temp=temp->next;
}
}
This was one of the question in my test and I couldn't find anything wrong in the above given code. I even ran this code in the compiler and it works fine.
Can anyone tell where the error is?
Node *temp = new Node; // a pointer, called temp, allocated to a new block
//of memory of size Node
temp = front // the pointer to the block of memory was just overwritten, and now you
//don't have a pointer to the block of memory you just allocated
First, you don't need to call new here. Just declare the pointer and assign it at the same time.
Second, since you did call new, you've just created a memory leak, that is, you've allocated memory that now has no way of being deallocated (until the program shuts down).
Third, you should access front with an accessor method.
myList.GetFront() //this should return a pointer to the front of the list
Why? Well, what happens if you accidentally do something like:
front = front->next;
You've just lost the pointer to the front of your list, and so has every other method that uses front.
I have this small piece of code in my IntList implementation to push_back nodes. My question is if the *pnode cause memory leak or do I need to delete it at the end.
void IntList::push_back(int data){
if (first){
IntNode *pNode = first;
while(pNode->next!=0){pNode = pNode->next;}
pNode->next = new IntNode(data);
} else
first = new IntNode(data);
}
No you don't need to call delete on pNode. You only call delete on things created with new. With the code as it is now pNode is a stack object and will automatically be destroyed when it goes out of scope at the end of the function.
You don't need delete pNode. Moreover, you can't do it in this particular case.
After you create something with new you must delete it exactly one time - once you'll never use it.
After removing the object with delete, attempt to read its contents is an undefined behavior. The pointers are generally one of the most bug generating part of the c++, so it is good that you are trying to understand it better.
You can visualize yourself this way: You can buy a house (house is a piece of memory) with new. It returns you address if it. It is your house now and can do with it what you want. You can also sell it with delete. Until this is done, you can give your friend your home address so that they can come to you. Distribution of the address, causing copying it (e.g. IntNode *pNode = first;). However, you still have only one house. So no matter how many times you copy your home address, you can sell the house only once.
I would advise using smart pointers (e.g. std::unique_ptr), but I think this program is for learning programing, so don't do it ;)
You have to delete the IntNodes created with new eventually, likely in the destructor of the container and the pop_back function. pNode itself (the pointer) was allocated on the stack, and not with new, so does not need to be deleted.
You need delete nodes on each function that removes nodes from the list, not when inserting. Not doing so would cause a leak.
If there are still allocated nodes when you destruct the object you need to iterate the whole list to remove all the nodes too. Not doing so would cause a leak too.
I suppose that this is a college assignment, as there are millions of battle-tested linked list implementations out there.
You'd do better if you maintain a tail node up to date on all functions, so you could avoid iterating the whole list to insert a node on the tail.
The code you show is not sufficient to tell if you're leaking memory or not. You show the routine responsible for allocation, but not the code where you're performing deallocation.
If you don't have any code performing deallocation, then yes, obviously that leaks. C++ does not perform automatic garbage collection as you may be used to in some other languages.
You are using naked new, so even if you do have some other code attempting to do deallocation, there's a good change it's being done incorrectly.
In C++ you generally shouldn't be using the new operator directly, and you should learn to use RAII to handle resources instead. IntList presumably uses owning raw pointers, which is another thing to be avoided. In this case you should probably be using unique_ptr<IntNode>. For example:
struct IntList {
struct IntNode {
unique_ptr<IntNode> next;
int data;
IntNode(int data) : data(data) {}
};
unique_ptr<IntNode> first;
// returns a reference to the null pointer which terminates the linked list
unique_ptr<IntNode> &get_tail() {
if (!first) {
return first;
}
IntNode *pNode = first.get(); // pNode is a non-owning pointer
while (pNode->next) {
pNode = pNode->next.get();
}
return pNode->next;
}
void push_back(int data) {
get_tail() = make_unique<IntNode>(data);
}
};
There actually is a problem with the above code, but the issue is unrelated to memory leaks. When the list is destroyed, first is automatically destroyed, which automatically destroys first->next, and so on. It's possible to insert so many elements into the list that this chain of destruction 'smashes' the function stack, leading to undefined behavior.
The problem can be fixed with an IntList destructor that destroys the nodes in the opposite order:
IntList::~IntList() {
while (first) {
unique_ptr<IntNode> tmp = std::move(first);
first = std::move(tmp->next);
}
}
It's interesting that this is an example of an exception to the Rule of Three.
my node contains an int and a string variable, and I tried using binary search tree. the code is as follow:
struct node{
int a;
string members[5];
};
int main(){
node * root = NULL;
root = (node*)malloc(sizeof(node));
root->members[0] = "aaaaa";
return 0;
}
of course, my code wasn't exactly like that, I made it short in main because I want to show just the problem. it gave me 'access violation writing location'. I tried using 'new node();' instead of malloc and that didn't happen. why is this exactly?
malloc() only allocates memory. It doesn't call the constructor of the object. You could call the constructor on allocated memory using, e.g.
void* mem = malloc(sizeof(node));
if (mem) {
node* root = new(mem) node;
// ...
}
When using new node instead of malloc(sizeof(node) the allocate memory also gets initialized. Using an uninitialized object is undefined behavior.
malloc only allocates raw storage. new allocates raw storage and initializes it to contain a specified type.
If you're allocating only POD types, that distinction is mostly one of wording, with little real difference in what happens.
If you're allocating something like an std::string that has a constructor, there's a world of difference though. If you use new, then your string variables have all been initialized so they're real (albeit, still empty) strings. When you just use malloc, they haven't been initialized at all--they're just chunks of uninitialized raw storage the right size to contain a string. When you try to use them as a string, a quick crash is about the best you can hope for.
Just as the title suggests, I am attempting to insert a value into an object pointer's string.
In my header, my object looks something as follows:
typedef struct d_tree
{
std::string name;
d_tree *parent;
std::vector<d_tree> dirs;
std::vector<t_file> files;
} tree_node;
(It's an assignment dealing with modeling a file and directory system for the curious.)
For the sake of my simplicity, I'm using strings and vectors (to avoid nuances of char * and double pointer arrays)
Now, for the head of this directory tree, I have in my source:
tree_node *G = (tree_node *)malloc(sizeof(tree_node));
getline(dirs, dirp); //First should be main parent, or ./
G->name = dirp;
G->parent = NULL;
tree_node *top = G;
tree_node *curr = G;
The allocation runs fine and well, and the getline is only for reading some string data I'll be using...but once I hit the G->name = ..., My compiler (Using VS 12) yells:
" First-chance exception at 0x57AD11CE (msvcr110d.dll) in File_System.exe: 0xC0000005:
Access violation writing location 0xCDCDCDCD.
If there is a handler for this exception, the program may be safely continued. "
Upon looking at the local variables before the exception gets thrown, I notice a few things: the name variable in G has an in the value column.
The parent variable also seems odd, but I won't worry about it just yet (esp. as I'm making it NULL, anyway..)
Any advice on how to alleviate this problem (preferably keeping strings, but understandable if no smooth solution exists) is greatly appreciated.
You're using malloc to allocate a struct of non-POD types. malloc only allocates memory, it does not construct the the non-POD members of the allocated struct. Consequently, when you try to assign to that struct's non-POD members, you're invoking each member type's assignment operator on a garbage object.
Use new tree_node() instead. (And also use delete instead of free to release the memory when you're done. Or better yet, assuming that you have a true tree without cycles, use smart pointers to release the memory for you.)
Incidentally, you don't need to do
typedef struct tag { ... } typename;
in C++; just
struct typename { ... };
is equivalent.
You need to use new, to create tree node, so that name's constructor will be called to initialize it.
//tree_node *G = (tree_node *)malloc(sizeof(tree_node));
tree_node *G = new tree_node;
This should work.
Although if you really need to allocate memory with malloc for some reason, you can use placement new.
void* gptr = malloc(sizeof(tree_node));//Allocate memory
tree_node *G = new(gptr) tree_node;//construct object in allocated memory
//Do whatever you want with G
G->~tree_node();//Explicitly call destrutor
free(gptr);//free memory
I have a question concerning deleting a dynamic array of pointers in C++. Let's imagine that we have a following situation:
int n;
scanf("%d", &n);
Node **array1 = new Node*[n];
/* ... */
where Node is a certain structure defined beforehand. Suppose that after allocation with the new operator, we change the content of the array1 (but we do not delete anything!). What is the proper way to delete the array1 and all its content if there is a possibility of repeated pointers in the array (without sorting them or inserting into the set, in linear time)?
Using this allocation:
Node **array1 = new Node*[n];
The contents of array1 are undefined. Each element is a Node*, and because the memory is uninitialized, the value could be anything.
Allocating an array of pointers does not construct objects of the pointed-to class.
So whatever pointers you put into the array, the objects they point to need to be constructed and destructed elsewhere.
So to answer your question, the proper way to delete array1 is
delete[] array1;
However, note that this will not result in destructors being called for each Node* - you should deal with whatever you put into the array before you delete the array.
EDIT:
I was confused by the original question, which mentioned "change the value" in the array, as if there was a valid value in the array as allocated in your example.
BUT... now that I understand you want to keep track of the pointers for deletion later, perhaps you can just create another array for that purpose where each pointer exists only once. So you have the array you currently have above, which contains pointers to nodes that might be repeated, for whatever purpose you're using it. Then you have another array for the express purpose of managing the deletion, where each pointer occurs only once. It should be easy enough to set something like nodeCleanupArray[i] = pNewNode right after pNewNode = new Node(), then you can blast through that array in linear time and delete each element. (Which means you wouldn't bother inspecting the elements in array1, you'd rely on nodeCleanupArray for the cleanup)
There are MANY solutions to this sort of problem, but the most obvious choice would be to change it to use
std::vector< std::shared_ptr<Node> >
Now you will have a reference counted pointer without writing any code, and an "array" that doesn't need to know it's predefined size.
You can of course implement a reference counted object within Node, or your own container object to do the same thing, but that seems like extra hassle for little or no benefit.
Try mark and sweep :) You are trying to implement a managed environment.
Here is an example:
struct Node
{
...
bool marked;
Node() : marked(false)
{}
};
Now delete:
void do_delete(Node **data, size_t n)
{
size_t uniq = 0;
Node **temp = new Node*[n];
for (size_t i = 0; i < n; i++)
{
if (data[i] && !data[i]->marked)
{
data[i]->marked = true;
temp[uniq++] = data[i];
}
}
for (i = 0; i < uniq; ++i)
{
delete temp[i];
}
delete[] temp;
delete[] data;
}
The way I'd do this is have a reference counters and have a Node::deref method that would delete the node itself when reference count is 0. When iterating through the list of nodes, calling node->deref will not actually delete the object until the last Node reference in the array.
What is the proper way to delete the array1 and all its content
You show a single allocation; new Node*[n]. This allocation confers on the program the responsibility to call delete [] whatever_the_return_value_was. This is only about deleting that one allocation and not about deleting 'all its content'. If your program performs other allocations then the program needs to arrange for those responsibilities to be handled as well.
if there is a possibility of repeated pointers in the array
Well it would be undefined behavior to delete a pointer value that is not associated with any current allocation, so you have to avoid deleting the same pointer value more than once. This is not an issue of there being a single correct way, but an issue of programming practices, design, etc.
Typically C++ uses RAII to handle this stuff automatically instead of trying to do what you want by hand, because doing it by hand is really hard to get right. One way to use RAII here would be to have a second object that 'owns' the Nodes. Your array1 would then simply use raw pointers as 'non-owning' pointers. Deleting all the Nodes then would be done by letting the Node owning object go out of scope or otherwise be destroyed.
{
// object that handles the ownership of Node objects.
std::vector<std::unique_ptr<Node>> node_owner;
// your array1 object that may hold repeated pointer values.
std::vector<Node*> array1;
node_owner.emplace_back(new Node); // create new nodes
array1.push_back(node_owner.back().get()); // put nodes in the array
array1.push_back(node_owner.back().get()); // with possible duplicates
// array1 gets destroyed, but it's contents do not, so the repeated pointers don't matter
// node_owner gets destroyed and destroys all its Nodes. There are no duplicates to cause problems.
}
And the destruction does occur in linear time.