I have buggy behaviour in C++ code that seems to be caused by the incorrect freeing of dynamically created structs. The structs are in the form:
typedef struct
{
char *value;
} Element;
typedef struct
{
int num;
Element **elements;
int *index;
} Container;
They are created like this:
Element *new_element(int size)
{
Element *elem = new Element;
elem->value = new char[size];
return elem;
}
Container *new_container(int num)
{
Container *cont = new Container;
cont->num = num;
cont->elements = new Element*[num];
cont->index = new int[num];
}
What is the correct way to free these?
You can easily fix all freeing problems by outsourcing resource management to the compiler:
#include <cstdlib>
#include <string>
#include <vector>
struct Element {
Element() = default;
explicit Element(std::size_t size) : value(size, '\0') { }
std::string value;
};
struct Container {
explicit Container(std::size_t size) : elements(size), index(size) { }
std::vector<Element> elements;
std::vector<int> index;
};
For all your future resource management problems, see The Definitive C++ Book Guide and List.
You should be doing this a sensible way. As others have pointed out, it can be made automatic. Failing that you should clean up in destructors. Failing that, however, and to answer the actual question, the syntax for deleting a new array is:
int x = new x[20];
delete [] x;
You will of course have to delete everything you new, so you will need to loop through the elements deleting each one in turn before deleting the elements array itself. You'd think someone would have wrapped that up in a convenience type cough vector cough.
Related
This is not a real question, since I've already solved the problem myself, but I still need some clarifications about the mechanism behind assigning an array's address to a pointer of the same type when the array is a class member of a nested class.
The following code is fully functioning, although it may lack some error_check. It is only meant to show how I made my (real) program work.
HEADER (linkedList)
class linkedList
{
public:
linkedList();
~linkedList();
int* getArray();
void forward();
private:
class listNode
{
public:
listNode();
~listNode();
friend class linkedList;
private:
int array[3];
listNode* next;
};
listNode *first;
listNode *current;
};
CPP (linkedList)
linkedList::linkedList()
{
first = new listNode;
current = first;
}
//~~~~~~~~~~~~
linkedList::~linkedList()
{
delete first;
first = 0;
current = 0;
}
//~~~~~~~~~~~~
int* linkedList::getArray()
{
if (current)
{
return &(current->array[0]);
}
}
//~~~~~~~~~~~~
void linkedList::forward()
{
if (current->next)
{
current = current->next;
}
}
//-------------------------
//-------------------------
//-------------------------
linkedList::listNode::listNode()
{
next = 0;
for (int i = 0; i < 3; i++){array[i]=((i+1)*3);}
}
//~~~~~~~~~~~~
linkedList::listNode::~listNode()
{
}
CPP (main)
#include <iostream>
#include "linked_list.h"
using namespace std;
int main()
{
linkedList list;
int *myArray;
myArray = list.getArray();
for (int i = 0; i < 3; i++){cout << myArray[i] << " ";}/**/cout << "\n\n";
return 0;
}
The real program is meant to move through a linked list made of nodes which contain 3 integer values in an array of int type, retrieve the three values and use them as parameters for some other functions.
Now, to do so I have to return the address to the first element of the array contained in the node through an accessor.
Apparently, the only way to do it is by returning the reference to the first element of the array in the node to which the linkedList's member variable current points to:
return &(current->array[0]);.
Why?
I've got to this solution through trial and error with very little knowlegde of the reasons that brought me to build this expression as it is.
Usually, when you want to assign the address of an array to a pointer, you just do so:
int main()
{
int array[3];
int* pArray;
pArray = array;
}
And that's it, because the name of the array itself is enough to retrieve the address of its first element.
The exact same result can be achieved by doing this (tested):
int main()
{
int array[3];
int* pArray;
pArray = &(array[0]);
}
Both methods are also valid when the accessor returns the address from a member variable of its own class.
But why, when accessing the member variable of a nested class, I'm forced to use the second method?
What are the logic stages that make it the only viable method?
But why, when accessing the member variable of a nested class, I'm forced to use the second method?
You aren't:
return current->array;
and
return &(current->array[0]);
Both do the same thing when the return type is int*. You aren't forced to use the second way.
Also, there's a bug in getArray. You don't return anything if current is null.
To be pedantic...
Apparently, the only way to do it is by returning the reference to the first element of the array in the node to which the linkedList's member variable current points to:
return &(current->array[0]);.
You're returning the address i.e. a pointer. Reference means something else.
struct node {
std::vector<struct node*> * list;
}
int main() {
struct node * n = new struct node;
n->list = new std::vector<struct node*>();
n->list->push_back(n);
return 0;
}
How can I delete the n->list with freeing all the pointers that the list is storing?
Will it be n->list->clear()? Or do I have to traverse n->list and call delete or free operator on each element in the list.
std::vector does not assume ownership of dynamically created objects.
(Even if it wanted to, or you created a specialisation or your own implementation, it's impossible to distinguish dynamic allocations from other pointers.)
You need to traverse the vector and free the elements.
The safer/simpler would be
struct node {
std::vector<node> list;
};
int main() {
node n;
n.list.resize(1);
}
or if you need pointer:
struct node {
std::vector<std::unique_ptr<node>> list;
};
int main() {
node n;
n.list.push_back(std::make_unique<node>());
}
First of all: you don't need so much pointers.
If you want it be be this way, you should delete it exactly the same way you have 'newed' it :).
In your example:
int main() {
struct node * n = new struct node;
n->list = new std::vector<struct node*>();
n->list->push_back(n);
delete n->list; // here's the change
delete n; // another required delete
return 0;
}
But as I said, too much news.
You can write your struct node as:
struct node {
std::vector<struct node*> list;
}
it will cause the list to be automatically deleted when node object is being deleted.
This line: struct node * n = new struct node; also can be converted into:
node n;
I have this struct:
struct problem
{
int length;
struct node **x;
};
and I created a struct of this struct like this:
struct problem prob;
I can do this in C:
prob.x = Malloc(struct node *,prob.length);
but how I can do it in c++ style with new ? and why ?
In C++, it would be achieved with this.
std::vector<node *> problem(length);
The code you show is effectively emulating a small subset of the features of vector. Namely, an array-like container that is aware of its size.
Ok, this code might work, note that you are no longer holding a pointer to a pointer, but a simple array - which may or may not work for what you are trying to do:
typedef struct tagnode
{
...
} node;
typedef struct tagproblem
{
int length;
node *x;
tagproblem(int len) : length(len)
{
x = new node[length];
}
~tagproblem()
{
delete [] x;
}
} problem;
//Now create...
problem = new problem(2);
I have a class, which I'll refer to as myclass, that has a list container of the type T. I also have a couple of methods that remove items from the list. Should the T be a pointer of some sort, I would like to check that it indeed is a pointer and then delete it in order to relieve allocated resources back to memory. Here's a snippet of code:
template<typename T>
class myclass{
private:
std::list<T> * container;
// other vars
public:
void erase(const T &item){
if (!this->find(item)) // find is defined elsewhere
return false;
auto temp = container->begin();
for (int i = 0; i < container->size(); ++i){
// this is where i would like to check if *temp is a pointer,
// so that I can assign it to a pointer var, remove it from the list,
// then delete the pointer,
//otherwise just simply remove it from the list.
}
}
};
EDIT
auto temp = container->begin();
I want to know how to determine if *temp is a pointer so that I can do the following:
T * var = *temp;
container->remove(temp); // remove or erase, i can't recall at the moment
delete var;
but I only want to do that if *temp is a pointer
1) Determine if Type is a pointer in a template function
2) How would you know if that pointer is pointing to dynamically allocated memory?
I don't think this is a wise idea. You don't know whether the user has provided pointers to data allocated on the stack, or to data that is managed in some other way (eg with smart pointers).
But to answer the question, look at
std::is_pointer<T>::value // in type_traits header
http://en.cppreference.com/w/cpp/types/is_pointer
This is a C++11 feature.
Sorry, but no: std::list<T>::iterator (which is what begin() will return and therefore will be the type of temp) can't ever be a pointer. It must be a type that (at the very least) overloads pre- and post-increment and decrement to do linked list traversal so ++ will do something like pos = pos->next; and -- will to something like pos = pos->prev;.
If you're trying to figure out if *temp (which will be the same type as T) is a pointer, that's a whole different story. You basically have two routes. The one I'd prefer as a general rule would be to provide a specialization of your class for pointers:
template<typename T>
class myclass{
private:
std::list<T> container;
// other vars
public:
void erase(const T &item){
if (!container->find(item)) // find is defined elsewhere
return false;
auto temp = container->begin();
for (int i = 0; i < container->size(); ++i){
container.erase(temp);
}
}
};
template<class T>
class myclass <T *> {
private:
std::list<T> container;
// other vars
public:
void erase(const T &item){
if (!container->find(item)) // find is defined elsewhere
return false;
auto temp = container->begin();
for (int i = 0; i < container->size(); ++i){
delete *temp;
container.erase(temp);
}
}
};
The biggest problem with this is that you may end up duplicating a fair amount between the base template and the specialization for pointers. There are a couple of ways of avoiding that. One is to use a base class that implements the common behavior, then derive the two specializations from that to provide the specialized behavior. Another would be to use some enable_if or SFINAE to enable different versions of the erase function depending on whether the contained type is something that can be dereferenced or not.
As an aside, you probably shouldn't have std::list<T> *container; -- it should probably be just std::list<T> container; (or, better still in most cases, std::vector<T> container;)
Isn't it annoying container's don't delete normal pointers? Well in C++ raw pointers don't actually own the object. There could be many pointers pointing to the same object. You need a unique pointer - stl provides one in c++11. When a unique_ptr is removed from the list, it will destroy the object it points to, so there is no need to complicate erase.
#include <list>
#include <memory>
#include <type_traits>
using namespace std;
template<typename t, bool b>
struct Selector {
typedef list<T> container;
};
template<typename t>
struct Selector<t, true> {
typedef list<unique_ptr<T> > container;
};
template<typename T>
class myclass{
private:
Selector<T, is_pointer<T>::value>::container* container;
// other vars
public:
void erase(const T &item){
if (!this->find(item)) // find is defined elsewhere
return false;
auto temp = container->begin();
for (int i = 0; i < container->size(); ++i){
// removing the unique_ptr delete's pointer
}
}
};
I have class cAuthorisation that manages array of strAuthorisation
function resize prepares aray for next record.
During resize , on line delete [] data; I have crash.
struct strAuthorisation
{
double Amount;
}Authorisation;
class cAuthorisation {
public:
int size;
strAuthorisation *data;
cAuthorisation ()
{
size=0;
}
~cAuthorisation()
{
};
void Add(strAuthorisation )
{
resize();
data[size]=*value;
}
void resize()
{
strAuthorisation *a = new strAuthorisation[5];
size_t newSize = size + 1 ;
strAuthorisation *newArr = new strAuthorisation[newSize];
memcpy( newArr, data, size * sizeof(strAuthorisation) );
size = newSize;
delete [] data;
data = newArr;
}
} Authorisations;
Why it is not possible delete class array?
It crashes because data is an unitialised pointer. delete[] on a null pointer is safe (no-op) so initialise data in the constructor:
cAuthorisation() : size(0), data(0) {}
Note that the class as it stands is violating the rule of three.
Unsure if this is a learning exercise, if it is not use std::vector<strAuthorisation>. The std::vector will dynamically grow as required and automatically destructed when it goes out of scope.
You have not initialized the data pointer. So you are making something like this:
Foo *data;
delete [] data;
"data" is a pointer who's value was never initialized.