initializing array of string in binary search tree - c++

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.

Related

initialize an empty unordered_map inside my structure in C++

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.

how to dereference a linked list node data that is a pointer?

so I am creating a linear linked list and I am not allowed to use static arrays or strings as data members (only dynamic char arrays)
so I have my data struct:
struct artists
{
char* name;
char* story;
char* description;
};
and my node representation:
struct node //Create our node type for LLL of artists
{
artists* data;
node* next;
};
I am planning to allocate memory for name,description, story inside a function but my question is how do I actually dereference this?
is there such thing as *(temp->data.name)?
Or does this code make sense at all?
name = new char[strlen(artistitle)+1]
strcpy (*(temp->data.name),artistitle)
or would it still be strcpy(temp->data.name,artistitle), since array names work similar to pointers.
I am a little confused, I might be way off, so any input will be appreciated, thanks.
As you are working with dynamic memory, first thing you should have in mind is how do you allocate memory, and free it. Second, how do you access that memory.
As your question, it seems that you want to access it, besides using dereference.
To obtain any value from a "normal allocated" struct/class, you can use . so, working with, eg: the artist name, would be:
artists a;
//Suposse you have allocated char pointer here
strcpy(a.name, artistname);
If you are working with dynamic memory, you must use -> operator as here:
artists *a;
//Dynamic allocate struct and char pointers
strcpy(a->name, artistname);
It is the same when you have nested pointers and "normal allocated":
node n;
//Allocate everything
strcpy(n.data->name, artistname);
//Another way to do it
node *n;
//You have to allocate node too
strcpy(n->data->name, artistname);
When you use a pointer as a variable, it stores the memory direction where it is pointing (ironic, huh). So if you do
node *a;
//Allocate it, and do some operations
node *b=a;
You are copying a's memory pointer, not its content. To access a pointer's content, you can use * operator.

Difference between setting a node equal to NULL vs. deleting a Node

Lets say I have a node struct defined as below :
struct Node
{
int data;
Node* left;
Node* right;
}
lets say i have a node Node abc and xyz and :
abc->data = 1;
abc->right=NULL;
abc->left=xyz;
xyz->data =2;
xyz->right=NULL;
xyz->left=NULL;
Later if i want to delete the node xyz, is it the same if i say:
delete xyz
vs. saying:
xyz=NULL;
Could someone explain the difference or point me in the right direction ?
No, it is not the same. delete X; statement actually calls a destructor of the object pointed by X and releases/frees the memory previously allocated for that object by operator new.
The X = NULL; statement simply assigns addres 0x0 to the pointer X and neither destroys the object pointed by X nor releases the memory as opposed to delete.
delete frees the memory, but does not clear the pointer.
setting the xyz to NULL just clear the pointer, but does not free the memory.
This is one of the many differences between C++ and Java/C#/JavaScript in its memory management -- in systems with Garbage collection the clearing of a reference/pointer such as xyz above will allow the garbage collector to later free the memory. C++ (or C) does not have garbage collection which is why memory must be managed as part of the program or otherwise you will end up with memory leaks.
As Vlad Lazarenko wrote above, these operations are not the same. In real code you should use smart pointers and do not call delete operator directly.
boost::shared_ptr<std::string> x = boost::make_shared<std::string>("hello, world!");
x->size(); // you can call methods of std::string through smart pointer
x.get(); // and you always can get raw pointer to std::string
Modern compilers allows you to write less code:
auto x = std::make_shared<std::string>("hello, world!");

C++: First-chance exception when assigning value to string in Object Pointer

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

C++ dynamic allocation program crashes

I have a very simple piece of code with 2 structures and one dynamic allocation. The program crashes on the "nume" initialization.
typedef struct{
int key;
string name;
} TElement;
typedef struct nod {
int cheie;
string nume;
struct nod *stg, *dr;
} NOD;
when i try to do this
void ABC::inserare_element(TElement e){
NOD *p, *q;
int n;
/* construction nod p*/
n=sizeof (NOD);
p=(NOD*)malloc(n);
p->cheie = e.key;
p->nume = e.name; // on this line the program crashes
Thanks
malloc() will not invoke the constructor of NOD, meaning the constructor of nume will not have been invoked resulting in an attempt to use std::string::operator= on an unconstructed/uninitialized std::string: use new.
You have a hot mix here of high-level C++ objects, such as std::string and C-style memory allocations such as malloc. The thing is that C++'s new operator not only allocates memory, but also calls constructor of high-level objects. The problem you are facing is that nume object of type std::string is not initialized properly, thus you run into undefined behavior that leads to a crash. That is because you are lucky. It could have been a lot worse if program was actually working, but producing strange, unexpected results.
To make it work like you want, you can simply use new instead of malloc. For example:
p = new NOD;
If it so happens that you really need to use malloc or other memory management API that does not care about C++ objects, then you have to call a constructor of nume manually, using a placement new. For example:
p = (NOD*)malloc(n);
new ((void *)&p->nume) std::string();
In case you go that way - don't forget to call destructor as well or you will end up with a memory leak.
You should use new instead of malloc. malloc is a C function and it only allocates a chunk of memory. Using new will call the default constructor of your class, and the string constructor will also be called at this moment.