I'm getting a segmentation fault on this program, and I know it has something to do with a null pointer being dereferenced, but I'm not exactly sure which one is causing the error. I'm just not certain as to how to fix the error while maintaining the purpose of the original program - it will compile, but at runtime I get the segfault I was just talking about.
main:
#include "link.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
link * head_pointer = new link(NULL, NULL) ;
for (int i = 0; i < 10; i++) {
string new_string;
getline(cin, new_string);
string* pointer_to_input = new string(new_string);
link * current_link = new link(head_pointer, pointer_to_input );
head_pointer = current_link;
}
head_pointer -> printAll(*head_pointer);
return 42;
}
link:
#include <string>
#include <iostream>
#include "link.h"
using namespace std;
link::link(link * pointer_to_link, string * pointer_to_string)
{
next = pointer_to_link;
value = pointer_to_string;
}
link::~link() {
delete value;
delete next;
}
link * link::getNext() {
return next;
}
string * link::getString() {
return value;
}
int link::printAll(link link_to_print) {
cout << *link_to_print.getString() << endl;
if (link_to_print.next != NULL) {
return printAll(*link_to_print.getNext());
} else {
return 0;
}
}
Your destructor does look like an error, you shouldn't delete in destructor if you didn't allocate that in constructor:
link::~link() {
}
You should post your link.h to get more detailed explanation.
Without link.h it's not clear what else is wrong, however, there are also other problems:
link::printAll looks like a static method and should be called as: link::printAll(head_pointer);
you printAll should take by pointer, otherwise it it will create a copy of your link and delete it.
printAll has multiple issues as well. Probably it should have been something as follows:
void link::printAll(link *link_to_print)
{
if (!link_to_print)
return;
if (link_to_print->getString())
cout << *link_to_print->getString() << endl;
printAll(link_to_print->next);
}
and your main:
int main()
{
link * head_pointer = new link(NULL, NULL);
for (int i = 0; i < 10; i++) {
string new_string = str;
getline(cin, new_string);
string* pointer_to_input = new string(new_string);
link * current_link = new link(head_pointer, pointer_to_input);
head_pointer = current_link;
}
link::printAll(head_pointer);
return 42;
}
In short to avoid errors you shouldn't store pointers to strings in your link, you should just store strings themselves. Your links perhaps shouldn't assume ownership of other links:
struct link
{
link *next;
string value;
link(link *next, const std::string& value) : next(next), value(value) {}
link * getNext();
const std::string& getString() const;
static void printAll(link *link_to_print);
};
link * link::getNext() {
return next;
}
const string& link::getString() const {
return value;
}
void link::printAll(link *link_to_print)
{
if (!link_to_print)
return;
cout << link_to_print->getString() << endl;
printAll(link_to_print->next);
}
and your main:
int main()
{
link * head_pointer = new link(NULL, "");
for (int i = 0; i < 10; i++) {
string new_string;
getline(cin, new_string);
link * current_link = new link(head_pointer, new_string);
head_pointer = current_link;
}
link::printAll(head_pointer);
// TODO: now you need to walk head_pointer and delete all links manually.
return 42;
}
Once you learn how memory management works in general you should most likely redesign your link using some kind of smart pointer helper class, such as unique_ptr or shared_ptr. And off course, once you master linked list you should start using std::list.
link::printAll takes its argument by value, which has two important effects:
The argument inside the function is a second link object created by making copies of the same value and next pointer.
The copy has automatic storage duration and is destroyed at the end of the function call.
Therefore, you have double frees going on. In particular, both the copy made in the recursive call and the sub-link of the original link share the same value pointer, and both try to delete it. The second deletion causes undefined behavior.
The solution is to respect the rule-of-three and not allow shallow copies of raw pointers. There are two possible approaches for managing objects owned by pointer:
Write a copy constructor to go with your destructor, so the two deletes mentioned above act on two different copies of the value.
OR
Use a smart pointer, such as std::shared_ptr, so you don't have to write a destructor by hand at all.
Note that you need a pointer to implement the connection between objects in the linked list, but you do not need a pointer to store the data. Having a data member of type std::string, instead of std::string *, would be just fine and do the right thing when copied (It makes sense to think of std::string as a smart pointer to an array of characters, that just happens to also have some extra string-manipulation functions tacked on).
Related
StackMeta_t *mystack_create(size_t objsize)
{
StackMeta_t *elem;
elem = (StackMeta_t*)malloc(sizeof(StackMeta_t));
if(elem == NULL)
{
return NULL;
}
else
{
elem->stack = NULL; // my actual stack basically the first elem(the top)
elem->objsize = objsize; // size of the datatype
elem->numelem = 0; // total count of elem inside the stack
}
return elem;
}
//PUSH
int mystack_push(StackMeta_t *data_stack, void* obj)
{
if(data_stack == NULL)
{
return -1;
}
StackObject_t *nodeObject = NULL;
nodeObject = (StackObject_t*)malloc(sizeof(StackObject_t));
if(nodeObject == NULL)
{
return -1;
}
nodeObject->obj = malloc(data_stack->objsize);
if(data_stack->stack == NULL)
{
nodeObject->next = NULL;
}
else
{
nodeObject->next = data_stack->stack;
}
memcpy(nodeObject->obj, obj, data_stack->objsize);
data_stack->stack = nodeObject;
data_stack->numelem++;
return 0;
}
So I am trying to translate my C code into C++ code. These are Linked List and Stacks data structure
I researched that the malloc() version of C++ is the new keyword. So creating memory for the
linked list nodeObject, I did StackObject_t *nodeObject = new StackObject_t;.
But the problem I encountered is creating memory for the obj of the Linked List. The data type for this variable is void* obj;. So that would be using a pointer to the objsize created with by the mystack_create(size_t objsize) function.
My question is, how do I convert nodeObject->obj = malloc(data_stack->objsize); to C++ while using the new keyword?
I tried doing nodeObject->obj = new data_stack->objsize; and the error gives me expected a type specifier. Do I need to cast data_stack->objsize? and what is the syntax for this for future reference? I have been coding with C for almost a year now and I know a few OOP from C#. Now I am just beginning to learn C++ and I couldn't find any answer for this type of situation.
You should probably not use void* in C++ - it's usually not a good idea to abandon the type system. Instead, use templates.
So instead of doing
struct StackMeta_t
{
//stuff
void* obj;
};
just do
template <class T>
struct StackMeta_t
{
//stuff
T* obj;
};
Whatever type you put as T is what controls the typing of obj; for example, StackMeta_t<int> would result in int* obj;, etc, unless you'd rather change the typing of obj halfway through your program, which is probably something you would not want to do anyways.
Also just use std::stack if you want to use a stack in C++.
If your goal is to use C++ instead of the old C methods, then you should go all the way and use the current guidelines. The current way to use pointers and memory management is through smart pointers.
The reason these are useful, especially for your case, is because they do both the memory management for you (allocation and de-allocation) and prevent memory leaks or "read-after-free" kind of bugs.
I did a simple implementation of your stack object using std::shared_ptr, which is appropriate in your case as you want to reference an external object in your obj* member.
struct StackObject
{
StackObject(void* p_obj)
{
obj = p_obj;
}
void* obj;
std::shared_ptr<StackObject> next;
};
struct StackMeta
{
int numelem;
size_t objsize;
std::shared_ptr<StackObject> stack; // First object
StackMeta(size_t p_objsize)
{
objsize = p_objsize;
stack = nullptr;
numelem = 0;
}
void push(void* obj)
{
std::shared_ptr<StackObject> newobj = std::make_shared<StackObject>(obj);
newobj->next = stack;
stack = newobj; // make the stack reference the newly created object
numelem++;
}
};
For this to function, you need to include memory.
To test this, I made a simple main():
int main()
{
StackMeta list(4); // 4 bytes for integers
int some_int1 = 48;
int some_int2 = 480;
int some_int3 = 148;
int some_int4 = 408;
list.push(&some_int1);
list.push(&some_int2);
list.push(&some_int3);
list.push(&some_int4);
StackObject* curr_obj_ptr = list.stack.get();
while(curr_obj_ptr != nullptr)
{
int curr_obj = *(reinterpret_cast<int*>(curr_obj_ptr->obj));
std::cout << "Current object: " << curr_obj << std::endl;
curr_obj_ptr = curr_obj_ptr->next.get();
}
return 0;
}
Which prints:
Current object: 408
Current object: 148
Current object: 480
Current object: 48
Please correct me if I misunderstood your implementation.
A final note: It is a very bad practice to use void* in C++. In our case, it forced us to call a reinterpret_cast which is not desirable. The correct approach is to use a template for the StackMeta and StackObject classes.
I am writing an auction program for a class project and one of the features I was trying to implement was a hash table to make searching for auction items by name efficient. I set it up in node format so that you can chain nodes together if their hash value lines up with another item that already exists.
The main problem that I cannot seem to figure out is how some pointer values are changing when I don't think I have done anything to them. I stepped through each line of this program keeping an eye on the Red highlighted areas in the attached screenshots to see when the data changes. In case #1 the data was intact and able to be accessed. However, in case #2 where I simply declare an additional variable (int i = 0;) suddenly the data passed into the function appears to point to a different memory location (0xcccccccc) which from what I understand is another version of null? This is the same no matter what variable type I have tried to declare whether it be an int, const char*, string, etc it all reacts like the second screenshot.
Does anyone know why the program would be doing this? Are there any other troubleshooting tips? Is this a common error and how should I avoid it in the future and for this project?
I can provide a complete code if needed. I appreciate any help you can provide.
Image 1: No additional variable declared, data in tact as expected
Image 2: integer variable declared, data at ->next suddenly changed. This appears to be this way from the start of the function.
Update: I created an MRE as suggested in a comment, the same error can be reproduced using this code.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
class AuctionItemBidsMaxHeap {
string name = "test";
public:
const char * getItemName() {
return name.c_str();
}
};
class AuctionItemHashTable {
private:
struct Node {
AuctionItemBidsMaxHeap* AuctionItem;
Node* next = nullptr;
};
Node* itemArray;
int capacity = 50;
int generateHashKey(string auctionItem) {
return 11;
}
public:
AuctionItemHashTable() {
//Create the array of X amount of different possible storage locations
Node emptyNode;
emptyNode.AuctionItem = nullptr;
emptyNode.next = nullptr;
itemArray = new Node[capacity];
for (int i = 0; i < capacity; i++) {
itemArray[i] = emptyNode;
}
}
~AuctionItemHashTable() {
delete itemArray;
}
void insertItem(AuctionItemBidsMaxHeap* auctionItem) {
//Check to see if this item already exists
int key = generateHashKey(auctionItem->getItemName());
Node newAuctionItem;
newAuctionItem.AuctionItem = auctionItem;
newAuctionItem.next = nullptr;
//Check to see if anything has been inserted there yet
if (itemArray[key].AuctionItem == nullptr) {
itemArray[key] = newAuctionItem;
}
else {
//WE have to make room in the semi-linked list
Node holder;
holder.AuctionItem = itemArray[key].AuctionItem;
holder.next = itemArray[key].next;
newAuctionItem.next = &holder;
itemArray[key] = newAuctionItem;
}
}
AuctionItemBidsMaxHeap* getAuctionItem(const char* itemName) {
int key = generateHashKey(itemName);
//Loop through all items in location
Node* currentNode = &itemArray[key];
if (currentNode == nullptr) {
return nullptr;
}
else {
if (currentNode->AuctionItem->getItemName() == itemName) {
cout << "Match" << endl;
}
while (currentNode->next != nullptr && currentNode->next != (void*)0xcccccccc) {
int i = 0;
if (currentNode->next->AuctionItem->getItemName()[0] == 'M') {
cout << "M Matched" << endl;
}
while (currentNode->next->AuctionItem->getItemName()[0] != 'e') {
//cout << currentNode->next->AuctionItem->getItemName()[i];
}
currentNode = currentNode->next;
}
//There was an item stored at this location, lets see which one it is
//void* p = (void*)0xcccccccc; //Creating a pointer since for some reason my final pointer gets changed to another type of null character upon passing it to a function
//cout << currentNode->AuctionItem->getItemName() << endl;
//while (currentNode->next != nullptr && currentNode->next != p) {
//cout << currentNode->AuctionItem->getItemName() << endl;
//currentNode = currentNode->next;
//}
return currentNode->AuctionItem;
}
}
};
int main()
{
/**Creating MaxHeap of one bid**/
AuctionItemBidsMaxHeap myBidTest;
AuctionItemBidsMaxHeap myBidTest2;
/**Creating Auction Item Hash Table**/
AuctionItemHashTable auctionItems;
auctionItems.insertItem(&myBidTest);
auctionItems.insertItem(&myBidTest2);
const char* myInput = "test";
auctionItems.getAuctionItem(myInput);
}
First a rant: Why is it that classes still teach pointers in C++? There are MUCH better ways to do this than Node*.
Your code contains several errors, but the most important one is here:
//WE have to make room in the semi-linked list
Node holder;
holder.AuctionItem = itemArray[key].AuctionItem;
holder.next = itemArray[key].next;
newAuctionItem.next = &holder; ////<<< ERROR HERE
itemArray[key] = newAuctionItem;
You create a temporary variable on the stack Node holder; This variable will be destroyed as soon as you leave the function.
But you take a pointer to this variable here
newAuctionItem.next = &holder;
IOW: Your list contains pointers to objects that no longer exist.
&holder is the address of the variable holder. As soon as holder goes out of scope, the contents of it will be destroyed. But newAuctionItem.next and as a consequence also itemArray[key].next will still point to the memory, where holder used to be.
This is what is called a dangling pointer.
I stopped reading your example, but it is also pretty dangerous to accept pointers to AuctionItems in your insert method. When you are using pointers here, you MUST MAKE SURE, that the actual objects remain valid for as long as they are in the list.
Or, to put it the other way round: You must remove them from your list before they get destructed. And we humans are not made to "make sure". We make errors, so it is better to write code where you cannot make an error like this (i.e. avoid pointers in the first place).
Another error: You are creating an array with itemArray = new Node[capacity];, but you are deleting it with delete itemArray;. When you are using new to create an array, you must use delete[] itemArray to delete it. See here delete vs delete[] operators in C++
A general note: DO NOT USE POINTERS AT ALL (unless you have to). Pointers are an advanced C++ concept.
You could use shared_ptr<> instead. This will take away the burdon of freeing the memory.
For your itemArray you could use std::vector<> instead of allocating an array with new[]; etc...
There are many good and easy to use classes in the C++ library, which will help you a lot writing safer and cleaner code.
Learning C++ is (at least) as much about learning the std Library as about learning the syntax and statements. std::vector<AuctionItemNodes> IS C++.
I'm testing out a class representing an dynamic array data structure I made for myself as practice with the language, but I ran into a problem where the destructor is called twice over, causing a heap corruption error.
So far, I have attempted to comment out some of the delete words. However, this leads to undefined behavior.
#include <iostream>
#include "windows.h"
#include <vector>
template<typename T> class Spider {
private:
T** pointer;
int maxSize;
int lengthFilled;
public:
//default constructor
Spider()
{
pointer = new T * [1];
maxSize = 1;
lengthFilled = 0;
}
//destructor
~Spider()
{
for (int i = 0; i < lengthFilled; i++)
{
pop();
}
delete[] pointer;
}
//Pushes an object in
void push(T thing)
{
if (lengthFilled == maxSize)
{
increaseSize();
}
T* thinggummy = &thing;
//then save its pointer in the functional array
pointer[lengthFilled] = thinggummy;
lengthFilled++;
}
//pops the array
void pop()
{
delete pointer[lengthFilled-1];
setSize(lengthFilled - 1);
lengthFilled--;
}
}
int main()
{
Spider<Spider<int>> test((long long)1);
for (int i = 0; i < 2; i++)
{
test.push(Spider<int>());
test.get(i).push(2);//this is implemented in the actual code, just omitted here
std::cout << test.get(i).get(0);
std::cout << "push complete\n";
}
system("pause");
return 0;
}
The expected results for this program should be:
2
push complete
2
push complete
Press any key to continue...
Instead, I get an critical error code in the debug log of "Critical error detected c0000374".
There are two issues here:
Like WhiteSword already mentioned, you are taking the address of a local variable when you do T *thinggummy = &thing. That is going to cause trouble since that address will be invalid as soon as you leave scope (unless maybe T resolves to a reference type).
You call delete on the things in the pointer array. However, these were not allocated via new. Instead they are just addresses of something. So you are trying to free something that was never allocted.
Currently I'm trying to use multiple classes (each with their own .cpp and header .h file) and link them using a main .cpp. I want to make a temporary new video object pointer, pass in the arguments, insert it into the linked list, and delete the temporary pointer. Afterwards, I need to print each individual node of the list.
Currently there are 4 files: main.cpp, vlist.cpp, vlist.h, video.cpp, and video.h
I am using vlist as a way to construct a linked list which gets passed in a video object pointer with the insert function defined in the vlist.cpp file.
The first problem being that I'm not sure I am doing that correctly. At the moment, all I'm doing to be able to pass a video object in another class is by including video.h in the vlist.h file.
The second problem is that I cannot figure out how to properly access the individual video object attributes in each node because my getter functions (defined in video.h) won't work. They seem to return an address rather than a value. However, whenever I try to fix that, it tells me that I cannot use the getter function like this.
My third and final problem is that in vlist.cpp I cannot pass in m_vid when creating a new node but I can pass in m_head just fine. It won't compile if I don't use myVid (a publicly declared video object pointer in vlist.h).
Files below:
main.cpp
#include <iostream>
using namespace std;
#include "vlist.h"
#include "video.h"
int main()
{
//Create temporary video object pointer using Video * temp = new Video(arguments);
//Pass in the temp video pointer to the list and insert it with VList function
string firstLine, secondLine, thirdLine = "";
float fourthLine = 1.1;
int fifthLine = 2;
VList list;
Video * tempVid = new Video(firstLine, secondLine, thirdLine, fourthLine, fifthLine);
list.insert(tempVid);
delete tempVid;
list.print();
return 0;
}
video.cpp
#include "video.h"
#include <iostream>
using namespace std;
Video::Video(string title, string URL, string comment, float length, int rating) {
vidTitle = title;
vidURL = URL;
vidComment = comment;
vidLength = length;
vidRating = rating;
}
void Video::print(Video *myVid) {
cout << myVid->getTitle() << endl;
}
video.h
#ifndef VIDEO_H
#define VIDEO_H
#include <string>
#include <iostream>
using namespace std;
class Video
{
public:
Video(string title, string URL, string comment, float length, int rating);
int getRating() {
return vidRating;
}
float getLength() {
return vidLength;
}
string getTitle() {
return vidTitle;
}
string getURL() {
return vidURL;
}
string getComment() {
return vidComment;
}
void print(Video *myVid);
private:
string vidTitle, vidURL, vidComment, vidPreference;
float vidLength;
int vidRating;
};
#endif
vlist.cpp
#include <iostream>
using namespace std;
#include "vlist.h"
VList::VList() {
m_head = NULL;
}
VList::~VList() {
Node *ptr = m_head;
while (ptr != NULL) {
Node *temp;
temp = ptr;
ptr = ptr->m_next;
delete temp;
}
}
void VList::insert(Video *myVid) {
m_head = new Node(myVid, m_head);
}
void VList::print() {
Node *ptr = m_head;
while (ptr != NULL) {
cout << ptr->m_vid->getTitle();
ptr = ptr->m_next;
}
}
vlist.h
#ifndef VLIST_H
#define VLIST_H
#include "video.h"
class VList
{
public:
VList();
~VList();
void insert(Video *myVid);
void print();
Video *myVid;
private:
class Node
{
public:
Node(Video *myVid, Node *next) {
m_vid = myVid;
m_next = next;
}
Video *m_vid;
Node *m_next;
};
Node *m_head;
};
#endif
The first problem being that I'm not sure I am doing that correctly.
At the moment, all I'm doing to be able to pass a video object in
another class is by including video.h in the vlist.h file.
No, you are not doing it correctly, In the file main.cpp you are creating a pointer to Video(i.e, a Video*) and passing it to void VList::insert(Video *myVid) function and at the next line you are deleting the pointer before printing it. Remember that, when you create pointers and pass it to a method its lifecycle is not managed automatically like a magic, you yourself need to manage the pointers (which is the most common issue beginners face, I too). So there are two fixes to this problem
First Fix
Not deleting the pointer in the main, since it is deleted in the destructor of the VList.
#include <iostream>
using namespace std;
#include "vlist.h"
#include "video.h"
int main()
{
//Create temporary video object pointer using Video * temp = new Video(arguments);
//Pass in the temp video pointer to the list and insert it with VList function
string firstLine, secondLine, thirdLine = "";
float fourthLine = 1.1;
int fifthLine = 2;
VList list;
Video * tempVid = new Video(firstLine, secondLine, thirdLine, fourthLine, fifthLine);
list.insert(tempVid);
// delete tempVid; // don't delete this pointer right here, since I've found that you are deleting the pointer in the destructor of VList
list.print();
return 0;
}
Second Fix
You might like to use something called smart pointers as of C++11 these are standardized! See std::unique_ptr and std::shared_ptr. They will automatically delete the pointers and guarantees no memory leaks.
The second problem is that I cannot figure out how to properly access
the individual video object attributes in each node because my getter
functions (defined in video.h) won't work.
Your second problem is related to first one as your are deleting the pointer before using it which causes undefined behaviour and the output you might be getting is like a garbage. isn't it?
For the sake of simplicity I would recommend using simple Video reference not pointers. Pass them by value and all your problems will evaporate.
To answer my own question and that of anyone who might see this. I just needed to change it around a bit and set a temp object pointer inside of print and cout a get function onto that. It's very late so I apologize if there are any errors. I was indeed getting an address like I thought.
void VList::print() {
Node *ptr = m_head;
while (ptr != NULL) {
Video *tempPtr = ptr->m_vid;
cout << tempPtr->getTitle() << endl;
ptr = ptr->m_next;
}
}
I have been using C# for around a year and have recently been testing my patience with the harsh world of C++.
I am trying to create an object orientated binary tree. I have stepped through the code and read up on reference parameter passing and use of const in C++ but cannot work out what I am doing to cause an Access Violation Error. I have ensured that the structure is created properly and the code completes the first line of main as expected, however calling toString seems to result in an error and I cannot work out why.
Here is the code so far:
// ExpressionCL.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
using namespace std;
template<class TData> class TreeNode
{
private:
TData Data;
const TreeNode<TData>* Left = nullptr;
const TreeNode<TData>* Right = nullptr;
void setData(TData data)
{
Data = data;
}
public:
TreeNode<TData>(TData data)
{
setData(data);
}
TreeNode<TData>(TData data, const TreeNode<TData>& leftNode, const TreeNode<TData>& rightNode)
{
setData(data);
setLeft(leftNode);
setRight(rightNode);
}
void setLeft(const TreeNode<TData>& leftNode)
{
Left = &leftNode;
}
void setRight(const TreeNode<TData>& rightNode)
{
Right = &rightNode;
}
TreeNode<TData> getLeft() const
{
if (hasLeft())
{
return Left;
}
}
TreeNode<TData> getRight() const
{
if (hasRight())
{
return Right;
}
}
TData getData() const
{
return Data;
}
bool hasLeft() const
{
if (Left != nullptr)
{
return true;
}
else
{
return false;
}
}
bool hasRight() const
{
if (Right != nullptr)
{
return true;
}
else
{
return false;
}
}
string toString() const
{
string treeString = "";
if (hasLeft())
{
treeString += Left->toString();
}
treeString += to_string(Data);
if (hasRight())
{
treeString += Right->toString();
}
return treeString;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
TreeNode<int> IntTree(1, TreeNode<int>(1), TreeNode<int>(2));
cout << IntTree.toString() << endl;
return 0;
}
Some guidance or further recommended resources would be great.
Your setLeft and setRight functions set off alarm bells. Storing the address of an object that was passed by reference is seriously asking for trouble, as the caller may destroy the object and then you are left with dangling pointers for Left and Right.
In fact that is exactly what you do. You pass temporary objects to your constructor, storing their address in Left and Right. Then you call IntTree.toString() which tries to use pointers to objects that no longer exist.
To fix this you need to need to use manual lifetime management for your nodes. That means the node must be created via new. You have the option of either using raw pointers (in which case you would document your interface carefully to note that the caller should call new, pass in the pointer, and not call delete after).
The other option is to use smart pointers which will track ownership of the objects, however you have a few other problems to solve before doing that.
Specifically, treeNode does not currently follow the Rule of Three. Fixing this is extremely important. At a minimum, disable copying so that you do not accidentally make copies of a treeNode (which will not behave properly until you start following the Rule of Three)).
Using smart pointer classes means you can follow Rule of Zero instead of Rule of Three which makes for much cleaner code (although it may be difficult to do straight off the bat if you're new to C++, there aren't any good online teaching resources that I know of besides SO).
You are calling the Treenode constructor with temporary values and storing in the treenode pointer to these temps.
After the constructor has finished, these temps are gone and in calling a function which uses pointers to those temps (toString), a crash is occurring.
Your design needs the values of the treeitems as long as the tree is used, because you store only pointers to those values in the tree.
You could change the design to store copies of the treenodes within the tree.