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.
Related
I have a C++ program that creates Huffman codes for all characters in file. It works good, but I want to create nodes without using new operator because I know that you shouldn't use it. I tried using a vector global variable for saving nodes but that doesn't work.
std::vector<Node> nodes;
Node* create_node(unsigned char value, unsigned long long counter, Node* left, Node* right) {
Node temp;
temp.m_value = value;
temp.m_counter = counter;
temp.m_left = left;
temp.m_right = right;
nodes.push_back(temp);
return &nodes[nodes.size() - 1];
}
Edit: I added more code, I did't really explained what doesn't work. Problem is in generate_code(), it never reaches nullptr. I also tried using Node and not Node* but the same thing happened.
void generate_code(Node* current, std::string code, std::map<unsigned char, std::string>& char_codes) {
if (current == nullptr) {
return;
}
if (!current->m_left && !current->m_right) {
char_codes[current->m_value] = code;
}
generate_code(current->m_left, code + "0", char_codes);
generate_code(current->m_right, code + "1", char_codes);
}
void huffman(std::ifstream& file) {
std::unordered_map<unsigned char, ull> char_frequency;
load_data(file, char_frequency);
std::priority_queue<Node*, std::vector<Node*>, Comparator> queue;
for (auto& node : char_frequency) {
queue.push(create_node(node.first, node.second, nullptr, nullptr));
}
while (queue.size() != 1) {
Node* left = queue.top();
queue.pop();
Node* right = queue.top();
queue.pop();
auto counter = left->m_counter + right->m_counter;
queue.push(create_node('\0', counter, left, right));
}
std::map<unsigned char, std::string> char_codes;
Node* root = queue.top();
generate_code(root, "", char_codes);
for (auto& i : char_codes) {
std::cout << +i.first << ": " << i.second << "\n";
}
}
The general answer is of course to use smart pointers, like std::shared_ptr<Node>.
That said, using regular pointers is not that bad, especially if you hide all pointers from the outside. I wouldn't agree with "you shouldn't use new", more like "you should realize that you have to make sure not to create a memory leak if you do".
In any case, for something like you do, especially with your vector, you don't need actual pointers at all. Simply store an index for your vector and replace every occurence of Node* by int, somewhat like:
class Node
{
public:
// constructors and accessors
private:
ValueType value;
int index_left;
int index_right;
}
I used a signed integer as index here in order to allow storing -1 for a non-existent reference, similar to a null pointer.
Note that this only works if nothing gets erased from the vector, at least not before everything is destroyed. If flexibility is the key, you need pointers of some sort.
Also note that you should not have a vector as a global variable. Instead, have a wrapping class, of which Node is an inner class, somewhat like this:
class Tree
{
public:
class Node
{
...
};
// some methods here
private:
vector<Node> nodes;
}
With such an approach, you can encapsulate your Node class better. Tree should most likely be a friend. Each Node would store a reference to the Tree it belongs to.
Another possibility would be to make the vector a static member for Node, but I would advise against that. If the vector is a static member of Node or a global object, in both cases, you have all trees you create being in one big container, which means you can't free your memory from one of them when you don't need it anymore.
While this would technically not be a memory leak, in practice, it could easily work as one.
On the other hand, if it is stored as a member of a Tree object, the memory is automatically freed as soon as that object is removed.
but I want to create nodes without using new operator because I know that you shouldn't use it.
The reason it is discouraged to use new directly is that the semantics of ownership (i.e. who is responsible for the corresponding delete) isn't clear.
The c++ standard library provides the Dynamic memory management utilities for this, the smart pointers in particular.
So I think your create function should look like follows:
std::unique_ptr<Node> create_node(unsigned char value, unsigned long long counter, Node* left, Node* right) {
std::unique_ptr<Node> temp = std::make_unique<Node>();
temp->m_value = value;
temp->m_counter = counter;
temp->m_left = left;
temp->m_right = right;
return temp;
}
This way it's clear that the caller takes ownership of the newly created Node instance.
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).
I am currently working on implementing something similar to this
(http://molecularmusings.wordpress.com/2011/06/27/config-values/)
while using the template system, so that i do not have to create a class for all types i want to support. Now the class itself works fine, but i am having trouble figuring out how to manage memory if i read config values from a file and save them to the list.
This is my ConfigSetting class:
#pragma once
template <typename T>
class ConfigSetting {
public:
static ConfigSetting* head;
static ConfigSetting* tail;
public:
ConfigSetting(const std::string& name, const std::string& synopsis, T initValue) : m_name(name), m_synopsis(synopsis), m_value(initValue)
{
this->addToList();
}
// Special constructor for int ranges
ConfigSetting(const std::string& name, const std::string& synopsis, T initValue, T minValue, T maxValue) : m_name(name), m_synopsis(synopsis), m_value(initValue), m_min(minValue), m_max(maxValue)
{
this->addToList();
}
ConfigSetting& operator=(T value)
{
this->m_value = value;
return *this;
}
inline operator T(void) const
{
return m_value;
}
static ConfigSetting* findSetting(const std::string& name)
{
if (head) {
ConfigSetting* temp = head;
while (temp != nullptr) {
if (temp->m_name == name) {
return temp;
}
temp = temp->m_next;
}
}
return nullptr;
}
private:
void addToList(void)
{
if (head) {
tail->m_next = this;
tail = this;
}
else {
head = this;
tail = this;
}
}
ConfigSetting* m_next;
const std::string m_name;
const std::string m_synopsis;
T m_value;
T m_min;
T m_max;
};
template<class T> ConfigSetting<T>* ConfigSetting<T>::head = nullptr;
template<class T> ConfigSetting<T>* ConfigSetting<T>::tail = nullptr;
And i am using it like this (from another class called ConfigReader):
ConfigSetting<std::string>* cf = new ConfigSetting<std::string>(key, synopsis, value);
Now my question is: What is the best way manage memory in this case? Since the list is static i cannot just run through the list deleting everything once the destructor gets called. I could be using shared_ptr like this:
shared_ptr<ConfigSetting<std::string>> sp(new ConfigSetting<std::string>(key, synopsis, value));
or another type of smart pointer? Maybe there even is more elegant solution i didn't think of.
As far as I can see, there is nothing in your implicit destructor that must be called to ensure proper operation. If that is true, you can just forget about cleaning up your lists. Trying to do so will only increase the runtime of your program with absolutely no benefit. Just let the kernel do its job, it won't leak any memory pages just because you couldn't be bothered to clean up static data.
However, if you have a nontrivial destructor down the line somewhere which includes such important operations like flushing files or sending messages to other processes, then you must use a destructor function. I'm not talking about the normal C++ destructors here, but about a specially declared function that is executed by the runtime after main() exits.
With gcc, you declare a destructor function like this:
void foo() __attribute__((destructor));
void foo() {
//Do vitally important cleanup here.
}
Since the linker takes care of instructing the runtime to call your destructor function, you do not have to have any call to these functions, they may actually be declared with file local visibility.
Now, you ask "Am I not supposed to delete this pointer somewhere?" Yes, you are supposed to delete it. You are supposed to call delete on every object that you create with new for two reasons:
To give back the memory held by the object to the runtime, so that your process can reuse the memory for other purposes. If you fail to delete objects that you create on a regular basis, the memory footprint of your process will increase indefinitely until the kernel steps in and shoots down your process.
To run the destructor for your object, which frequently results in calling delete on other objects which are not needed anymore. In most cases, this will just give back more memory according to 1., which seems to be your case. It may do more vital operations, though.
Since the objects in question have to live until the very end of your process lifetime (they are static data, after all), you cannot possibly reuse their memory. The kernel, however, is above the level of the runtime that provides you with the new and delete keywords. The kernel is the creator of your tiny process world, in which the new and delete keywords happen to live. The kernel does not care about which parts of the virtual address space your runtime considers used/unused. The kernel will simply strip down the entire virtual address space when your process exits, and the used/unused state of your memory will dissipate into nothingness.
Title pretty much says it all, I'm almost positive it's either in the copy constructor or the assignment operator, and I'm pretty sure it's the latter. It's a pretty short class, so I'll post the entire thing, any advice on how to handle it would be good. I'm honestly a bit over my head here too, so any pointing to some solid reading would be greatly appreciated.
#pragma once
//for non-learning purposes, boost has a good smart pointer
template <class type>
class sPtr
{
private:
type *p;
int r; //referenceCount
void add()
{
r++;
}
int release()
{
return --r;
}
public:
sPtr(): p(NULL), r(1) {}
sPtr(type *pValue): p(pValue)
{
add();
}
sPtr(const sPtr<type> & sp): p(sp.p), r(sp.r)
{
add();
}
~sPtr()
{
if(release() == 0)
{
delete p;
}
}
type* get()
{
return p;
}
type& operator*()
{
return *p;
}
type* operator->()
{
return p;
}
sPtr<type>& operator=(sPtr<type> sp)
{
std::swap(this->p, sp.p);
std::swap(this->r, sp.r);
add();
return *this;
}
};
I'm pretty sure that the assignment operator should be passed by reference, but I'm not sure on how this will affect the implementation. I tried a few different implementations and all of them still had the leak.
Each of your shared pointers keeps track of its own separate reference count. This is obviously no good. When one is destroyed, the ref count on the others is not updated. You need to keep the reference count in a separate location that all the shared pointers have access to.
In addition to what Ben already mentioned, you are starting your reference count at 1 in your default constructor (and not initializing it at all in your others). If you assign a pointer to it after the default constructor, your reference count would be 2, and when you call release, back to 1. In short, the only time your reference count would be 0 (indicating you can delete the object) is if you call release 1 more time than add was called. Typically, you want those calls to be symmetrical (call to add corresponds to call to release).
I am writing a constructor for a binary search tree, the problem is that the helper function within the tree is being called infinitely, this eventually generates a stack overflow.
void copyTree(myTreeNode* & copy, const myTreeNode* & originalTree)
{
if(originalTree==NULL)
{
copy=NULL;
}
else
{
copy=new myTreeNode();
cout<<"This is the data my friend: "<<endl<<copy->data.getCharacter()<<endl;
copy->data=originalTree->data;
copyTree(copy->left, originalTree->getLeft());
copyTree(copy->right,originalTree->getRight());
}
}
//this is the copy constructor for the tree
myTree (const myTree & copy)
{
this->copyTree(this->root,copy.getRoot());
}
//and this is the way I have written the getLeft and getRight Functions
//they both return references to the left and rightNodes
const myTreeNode *& getLeft() const
{
const myTreeNode* ptr=NULL;
if(this->left)
{
ptr=this->left;
}
return ptr;
}
P.S the data object is not a primitive data type but it has no dynamic memory allocation.
I'm not sure how this might be causing infinite recursion, but your getLeft() function seems suspect. You're returning a reference to something on the stack. Who knows what's happening to that memory after that. It looks like you keep on using that same slot in memory over and over again, so you might be creating a loop instead of a tree.
Change it so that it returns a pointer, not a reference to a pointer (remove the '&').
#JCooper figured it out -- I'm just providing sample code. The getLeft() function should look more like this. Please note that I am NOT creating any NEW variables, so there is no stack lifespan problem.
const myTreeNode * getLeft() const
{
//may be NULL
return this->left;
}
(EDIT: made code more concise. Thanks #molbdnilo!)