Using malloc/free with classes - c++

I have some code that allocates memory for classes using malloc/realloc and then deletes them again using free. Below is an extract from what I'm working with:
void NewSubInstances()
// Invoked by each worker thread to grow the subinstance array and
// initialize each new subinstance using a particular method defined
// by the subclass.
{
if (slavetotalspace >= totalobj) { return; }
//Remember current large size
G4int originaltotalspace = slavetotalspace;
//Increase its size by some value (purely arbitrary)
slavetotalspace = totalobj + 512;
//Now re-allocate new space
offset = (T *) realloc(offset, slavetotalspace * sizeof(T));
if (offset == 0)
{
G4Exception("G4VUPLSplitter::NewSubInstances()",
"OutOfMemory", FatalException, "Cannot malloc space!");
return;
}
//The newly created objects need to be initialized
for (G4int i = originaltotalspace; i < slavetotalspace; i++)
{
offset[i].initialize();
}
}
void FreeSlave()
// Invoked by all threads to free the subinstance array.
{
if (!offset) { return; }
free( offset);
offset = 0;
}
I know that malloc will not call the constructor of the class, but this is dealt with by the initialize function. My question is: how can I deal with the freeing of the memory in a way that will also call the destructor of the classes (the classes generally have dynamically allocated memory and will need to delete it)?
Thanks!

how can I deal with the freeing of the memory in a way that will also call the destructor of the classes (the classes generally have dynamically allocated memory and will need to delete it)?
The answer to your question looks like this:
void FreeSlave()
{
if (!offset)
{ return; }
// call destructors explicitly
for(G4int index = 0; index < slavetotalspace; ++index)
offset[index].~T();
free( offset);
offset = 0;
}
That said, DO NOT use malloc/realloc/free in C++ (no, not even if any excuse goes here). While it will probably work (not sure on this), this code is obscure/has non-obvious dependencies, is brittle, difficult to understand, and it violates the principle of least surprise.
Also, please do not call your pointer "offset" and do not use C-style casts in C++ (it's bad practice).

You may use :
void FreeSlave()
{
if (!offset) { return; }
for (G4int i = slavetotalspace; i != 0; --i) {
offset[i - 1].~T();
}
free(offset);
offset = 0;
}

I would recommend to have a destroy() method ... since you have already initialize() ... the way of calling the destructor, albeit that is allowed, is really ugly and feels like a hack (which is).

Related

How to delete class as this and set it as null in c++

So, I have an array of a class called "Customer"
Customer** customersarray[] = new Customer*[customer];
I'm receiving int customer with cin.
anyways, in customer.cpp, there is a method called void deactivate().
which goes like this:
void Custmoer::deactivate()
{
if (this != NULL)
remove this;
//this = NULL; I want to do this but it doesn't work.
}
and the purpose of this is to remove it from customer array when satisfies a certain condition. So for example,
for (int i = customer - 1; i >= 0; i--)
{
if (customersarray[i]->getAngerLevel() == 5) {
customersarray[i]->deactivate();
}
for (int z = i; i < customer - 1; i++) {
*(customersarray + z) = *(customersarray + z + 1);
}
customer--;
}
so my first questions are:
why does this = NULL not work?
is there a simpler way to remove something from pointer array when a condition is satisfied? (for example, remove all customers that has anger level of 5.)
Your mistake is thinking that you can remove something from a Customer* array by some magic inside the Customer class, but that's not true. Just remove a customer from the customer array where ever the customer array is. For instance using remove_if
#include <algorithm>
Customer** customersarray = new Customer*[customer];
...
customer = std::remove_if(customersarray, customersarray + customer,
[](Customer* c) { return c->anger() == 5; }) - customersarray;
This updates the customer variable to be the new size of the array, but doesn't free or reallocate any memory. Since you are using dynamic arrays and pointers you are responsible for that.
Which is why you should really not be using pointers or arrays, but using vectors instead.
std::vector<Customer> customerVector;
Life will be so much simpler.
Type of "this" is a constant pointer which means you cant change where it points
Your function can return a boolean and if its true just set your pointer to null
You'll be much better off using a std::vector, all memory memory management gets much safer. You cannot modify the this pointer, but that would be meaningless anyway:
It is a local variable, so any other pointer outside would not be changed, not even the one you called the function on (x->f(): the value of x is copied into this).
It contains the address of the current object - the current object is at a specific memory location and cannot be moved away from (not to be mixed up with 'moving' in the context of move semantics!).
You can, however, delete the current object (but I don't say you should!!!):
class Customer
{
static std::vector<Customer*> customers;
public:
void commitSuicide()
{
auto i = customers.find(this);
if(i != customers.end())
customers.erase(i);
delete this;
}
}
Might look strange, but is legal. But it is dangerous as well. You need to be absolutely sure that you do not use the this pointer or any other poiner to the current object any more afterwards (accessing non-static members, calling non-static functions, etc), it would be undefined behaviour!
x->commitSuicide();
x->someFunction(); // invalid, undefined behaviour!!! (x is not alive any more)
Similar scenario:
class Customer
{
static std::vector<std::unique_ptr<Customer>> customers;
public:
void commitSuicide()
{
auto i = customers.find(this);
if(i != customers.end())
{
customers.erase(i); // even now, this is deleted!!! (smart pointer!)
this->someFunction(); // UNDEFINED BEHAVIOUR!
}
}
}
If handling it correctly, it works, sure. Your scenario might allow a much safer pattern, though:
class Customer
{
static std::vector<std::unique_ptr<Customer>> customers;
public:
Customer()
{
customers->push_back(this);
};
~Customer()
{
auto i = customers.find(this);
if(i != customers.end())
customers.erase(i);
}
}
There are numerous variations possible (some including smart pointers); which one is most appropriate depends on the use case, though...
First of all, attending to RAII idiom, you are trying to delete an object before using its destructor ~Customer(). You should try to improve the design of your Customer class through a smart use of constructor and destructor:
Customer() {// initialize resources}
~Customer() {// 'delete' resources previously created with 'new'}
void deactivate() {// other internal operations to be done before removing a customer}
Then, your constructor Customer() would initialize your internal class members and the destructor ~Customer() would release them if necessary, avoiding memory leaks.
The other question is, why do you not use another type of Standard Container as std::list<Customer>? It supports constant time removal of elements at any position:
std::list<Customer> customers
...
customers.remove_if([](Customer foo) { return foo.getAngerLevel() == 5; });
If you only expect to erase Customer instances once during the lifetime of the program the idea of using a std::vector<Customer> is also correct.

Order of destructors

I have these kind of classes:
Game:
class Game {
private:
BoardField*** m_board_fields;
public:
Game() {
m_board_fields = new BoardField**[8];
for (int i = 0; i < 8; i++) {
m_board_fields[i] = new BoardField*[8];
}
}
Game::~Game() {
for (int i = 0; i < 8; i++) {
for (int j = 0; i < 8; j++) {
delete m_board_fields[i][j];
}
delete[] m_board_fields[i];
}
delete[] m_board_fields;
}
}
BoardField:
class BoardField {
private:
ChessPiece* m_piece;
....
public:
BoardField::~BoardField() {
delete m_piece;
}
}
And on the close of the program I get error in ~BordField:
Exception thrown: read access violation.
this was 0xFDFDFDFD.
Did I made my destructors incorrect? What is the best way to clear memory from multidimensional array ?
There is are two fundamental flaws in your design:
there is no clear ownership of the BoardFields: someone create it, someone else deletes it. It can work if you're very cautious but it's error prone.
you do not ensure the rule of 3 (or better 5): if you have any piece of code where you create a copy of either your Game or a of any BoardField the first object that gets destroyed will delete the m_piece pointer, and when the second object gets destroyed, it'll try to delete a second time the same pointer, which is UB.
There is a third important issue: you're over-using raw pointers:
if m_board_fields is a 2d array of fixed size, make it a fixed size array (aka BoardField* m_board_fields[8][8]). If you want to keep its size dynamic, use vectors.
a cell of m_board_field could be a pointer if there's some polymorphism expected. But this seems not the case here, as obviously ChessPiece is the polymorphic class. So better use plain fields instead of pointers (aka BoardField m_board_fields[8][8]).
Finally, instead of using raw pointer to ChessPiece, better use a shared_ptr<ChessPiece> : you don't have to worry about shallow pointer copies and double delete; the shared_ptr will take care of itself and destroy the object if it's no longer used.

do I HAVE to use the new keyword?

This isn't the code I'm working on but it's the gist of what I want to do.
object *objects; int totalObjects;
void addObject(object o)
{
objects[totalObjects] = o;
totalObjects++;
}
It's giving me an access error when I try this:
Unhandled exception at 0x00e8a214 in crow.exe: 0xC0000005: Access violation writing location 0xcccccccc
Am I going to have to use 'new' and if so do I have to create a new array to copy to every time? Can I just add or take elements from the array I'm using?
Why don't you just use std::vector?
std::vector<object> objects;
void addObject(object o)
{
objects.push_back(o);
}
..or
void addObject(const object &o)
{
objects.push_back(o);
}
to remove additional copying.
When it comes to implementing your own dynamic array without std::vector, Yes. you need to allocate new memory, and copy your array to new memory block. Here's my example code with malloc and placement new.
#include <stdlib.h> // for malloc/free
#include <new> // for placement new, std::bad_alloc
object *objects = nullptr;
size_t totalObjects = 0;
void addObject(const object &o)
{
object *old_objects = objects;
size_t old_size = totalObjects;
size_t new_size = totalObjects + 1;
object *new_objects = (object *)malloc(sizeof(object) * new_size);
if (new_objects == nullptr)
throw std::bad_alloc();
size_t i;
try
{
for (i = 0; i < old_size; ++i)
{
new (&new_objects[i]) object(old_objects[i]); // placement new
}
}
catch (...)
{
// destroy new_objects if an exception occurs during creating new_objects
for (size_t j = 0; j < i; ++j)
{
new_objects[i].~object();
}
free(new_objects);
throw;
}
objects = new_objects;
free(old_objects);
}
(I haven't tested the code yet >o<)
Note that I used malloc and placement new, not new operator. It's impossible to call copy constructor of each element of the dynamic array with array-new.
However, if your object is TriviallyCopyable, you can use realloc. It can be more efficient, because realloc can just expand memory block, without copying - if the memory is enough.
..And you can select multiple lines and just press TAB in Visual Studio (..or many other editors).
You declared an object pointer, but not yet allocated the actual memory to store object objects. Your assignment statement merely tries to copy the input object o into an unallocated array member.
This is why you should use new before the assignment. The new operator asks the system to allocate some memory in the required size, then return the address of that memory and assign it to the pointer. Then, the pointer points to that newly allocated memory and the assignment (or copying) can be made.
When you finished using the array space, you should free the allocated memory using delete.
Okay, I'm going to add an answer to my own question. Let me know if this is bad etiquette. I just wanted to post some of my own code to duel with yours.
#include <vector>
std::vector<object> objects;
okay so I want to have two arrays (vectors) for the objects and double for distances so I may end up with
std::vector<double> distances;
void swap(unsigned int a, unsigned int b)
{
objects.swap_ranges(a,b);
distances.swap_ranges(a,b)
}
I'm going by the cplusplus.com reference for this function so let me know if I have it wrong. I'm going to go through it and completely redo my code.
Is there a type like the matrix that will let me hold data of different types so I don't have to invent a new object to handle each one individually?
If what you wrote is the most efficient and fast way to do this then I'll make a new class to hold both items.
thanks :)

Memory of a variable or object automatically terminated of finish at the end of program than why we use destructor?

In the following program we are creating Circle object in local scope because we are not using new keyword. We know that memory of a variable or object automatically terminated of finish at the end of program than why we use destruct?
#include<iostream>
using namespace std;
class Circle //specify a class
{
private :
double radius; //class data members
public:
Circle() //default constructor
{
radius = 0;
}
void setRadius(double r) //function to set data
{
radius = r;
}
double getArea()
{
return 3.14 * radius * radius;
}
~Circle() //destructor
{}
};
int main()
{
Circle c; //defalut constructor invoked
cout << c.getArea()<<endl;
return 0;
}
Assuming memory as an infinite resource is VERY dangerous. Think about a real-time application which needs to run 24x7 and listen to a data feed at a high rate (let' say 1,000 messages per second). Each message is around 1KB and each time it allocates a new memory block (in heap obviously) for each message. Altogether, we need around 82 GB per day. If you don't manage your memory, now you can see what will happen. I'm not talking about sophisticated memory pool techniques or alike. With a simple arithmetic calculation, we can see we can't store all messages in memory. This is another example that you have think about memory management (from both allocation and deallocation perspectives).
Well, first of all, you don’t need to explicitly define a destructor. One will automatically be defined by the compiler. As a side note if you do, by the rule of the 3, or the 5 in c++11 if you declare any of the following: copy constructor, copy assignment, move constructor (c++11), move assignment (c++11) or destructor you should explicitly define all of them.
Moving on. Oversimplified, the RAII principle states that every resource allocated must be deallocated. Furthermore, over every resource allocated must exist one and only one owner, an object responsible for dealocating the resource. That’s resource management. Resource here can mean anything that has to initialized before use and released after use, e.g. dynamically allocated memory, system handler (file handlers, thread handlers), sockets etc. The way that is achieved is through constructors and destructors. If your object is responsible of destroying a resource, then the resource should be destroyed when your object dies. Here comes in play the destructor.
Your example is not that great since your variable lives in main, so it will live for the entirely of the program.
Consider a local variable inside a function:
int f()
{
Circle c;
// whatever
return 0;
}
Every time you call the function f, a new Circle object is created and it’s destroyed when the function returns.
Now as an exercise consider what is wrong with the following program:
std::vector foo() {
int *v = new int[100];
std::vector<int> result(100);
for (int i = 0; i < 100; ++i) {
v[i] = i * 100 + 5;
}
//
// .. some code
//
for (int i = 0; i < 100; ++i) {
result.at(i) = v[i];
}
bar(result);
delete v;
return result;
}
Now this is a pretty useless program. However consider it from the perspective of correctness. You allocate an array of 100 ints at the beginning of the function and then you deallocate them at the end of the function. So you might think that that is ok and no memory leaks occur. You could’t be more wrong. Remember RAII? Who is responsible for that resource? the function foo? If so it does a very bad job at it. Look at it again:
std::vector foo() {
int *v = new int[100];
std::vector<int> result(100); <-- might throw
for (int i = 0; i < 100; ++i) {
v[i] = i * 100 + 5;
}
//
// .. some code <-- might throw in many places
//
for (int i = 0; i < 100; ++i) {
result.at(i) = v[i]; <-- might (theoretically at least) throw
}
bar(result); <-- might throw
delete v;
return result;
}
If at any point the function throws, the delete v will not be reached and the resource will never be deleted. So you must have a clear resource owner responsible with the destruction of that resource. What do you know the constructors and destructors will help us:
class Responsible() { // looks familiar? take a look at unique_ptr
private:
int * p_ = nullptr;
public:
Responsible(std::size_t size) {
p_ = new int[size];
}
~Responsible() {
delete p_;
}
// access methods (getters and setter)
};
So the program becomes:
std::vector foo() {
Responsible v(100);
//
// .. some code
//
return result;
}
Now even if the function will throw the resource will be properly managed because when an exception occurs the stack is unwinded, that is all the local variables are destroyed well... lucky us, the destructor of Responsible will be invoked.
Well, sometimes your object can have pointers or something that needs to be deallocated or such.
For example if you have a poiner in you Circle class, you need to deallocate that to avoid memory leak.
Atleast this is how i know.

Do i have to delete wchar_t that i allocated with new?

Lets say i have a class like this:
class LolClass {
LPWSTR* stuff;
LolClass::LolClass(LPWCHAR lols) {
stuff = new LPWSTR[100];
for (int i = 0; i < 100; i++) {
stuff[i] = new wchar_t[wcslen(lols)+1];
wcsncpy(stuffs[i], lols, wcslen(lols)+1);
}
}
LolClass::~LolClass() {
delete[] stuff;
}
}
so if i call
LolClass* veryfunny = new LolClass(L"lol!");
it would make me 100 lol's, problem is when i call
delete veryfunny;
it deletes the pointer array but not the individual wchar_t's, if i try and loop through the wchar_t's and delete them then i just crash and i dont know what to do since i know for fact that they are still there even after i delete veryfunny (i checked by passing one of the pointers outside the class)
Thanks!
If you call
LolClass* veryfunny = new LolClass(L"lol!");
then you will eventually need to call:
delete veryfunny;
But for arrays, you need delete[]: stuff[i] = new wchar_t[n]; delete [] stuff[i];
In your code, you need to first loop over stuff and delete[] the elements, and then delete[] the array stuff itself.
Or just use a std::vector<std::wstring>.
Update: From what I understand, you're not actually worried about deleting *veryfunny, but rather about how to write a correct destructor for LolClass. Note that the destructor also gets invoked for global and automatic objects, e.g. { LolClass x(L"hello"); } /* boom */, so it doesn't really matter how you instantiate an object for LolClass. You have to get the class right in any case.
David Schwartz wins after all, the wchar's didnt let themselves be deleted because they werent null terminated