New/Delete with a Class that uses malloc

Pages: 12
Jan 12, 2009 at 9:42pm
I have a simple question. I need, for particular reason, to use malloc/realloc and free into a class in this way

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Class A {
    DATATYPE * pointer
  public:
    A();
    ~A();
};

A::A() {
  pointer = (DATATYPE*) malloc ( sizeof(DATATYPE) );
}

A::~A() {
  free(pointer);
}


My question is:

if I use this class as a pointer

1
2
3
4
A * a;
a = new A;
...
delete a;


Allocation/deallocation works perfectly or there are problems "mixing" new/malloc like I did in this example?

(My code work correctly. Constructor inizialize malloc and destructor call free to free memory allocated with malloc. New/delete should call constructor and destructor of calss A so it seems correct. I'm asking only a confirm).
Jan 12, 2009 at 9:44pm
I don't know why you "need" to use malloc/realloc/free. I think that would be a bad design issue that you should address.

However, you shouldn't have any problems as long as you manage the memory correctly.
Jan 12, 2009 at 9:59pm
It is becouse I need to use a library that initialize and destroy the memory allocated to a pointer in its own way (with special functions). Seeing the fact I need to make an array of this pointer (pointer of pointer) I think that it is more sure to use malloc instead of new or vector (so I can control step-by-step every memory allocation and reallocation steps).

Thank for your reply.
Jan 12, 2009 at 10:04pm
new just uses a malloc under the covers anyway. It's better practice to use a C++ method of allocation/de-allocation than a C one. So you gain nothing from using malloc. Even if making an array of pointers to a pointer.
Jan 19, 2009 at 6:58pm
I'm sorry but I don't agree with you.

My class is thinked to be used like a special "vector" container for Allegro Images.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class ImgVec {
  //a customized "vector" for BITMAP storage
  private:
    int numImage;
  	BITMAP ** Image;
  	void TruncateVec(int ID);
  public:
    int count();
    void AddImage(BITMAP * src);
    void AddImgVec(ImgVec * src);
    BITMAP * img(int ID);
    void Remove(int ID);
    void Remove(int ID1, int ID2);
    ImgVec();
    ~ImgVec();
};


Constructor uses malloc for BITMAP **
Evety Bitmap, when inserted with AddImage or AddImgVec is allocated in this way:
1) BITMAP ** reallocation to new "array" size
2) Every Single BITMAP * allocation with Allegro own function (load_bitmap or create_birmao);

When deleted new ImgVec runs destructor
1) Destroing single BITMAP * allocation with Allegro own function destroy_bitmap
2) freeing BITMAP ** with free

----

2 things in particular I have to mark.

1) Allegro (like the major part of Libraries) are written mainly for C and can be used both in C or C++ projects (so I cannot agree with you at 100%. Becouse, with the same reason I can say that it is not suggested to use 90% of libraries like Allegro, SDL, etc).
Functions like load_bitmap that expects you free memory with special function (in this case destroy_bitmap) will probably are more similar to a malloc allocation than a new allocation (even if I think is mainly assembler, so I don't know if it is total right what I'm saying), but I have to use them if I want to use allegro. And they are "C" functions, as I said before.

2) The alternative "vector" to resize double pointer is, in this case, useless (becouse my class itself is thinked to be a kind of a "vector" of Images).
First of all, the stl function called "vector" USES ITSELF MALLOC/REALLOC. If you don't trust me, see "stl_alloc.h".
Second I have no reason to manage extra-params of stl vector, seeing the fact my class is thinked to do all the work with its own functions.
Third If I want to don't use AT ALL malloc/realloc (and, applying strictly what you said, this can exclude "vector") the only way is to make an internal work with new, copying all the things into an other "new" pointer greater than before. But, this means at least 2-3 movement in the memory address (no-sense). Instead, realloc, move the memory address ONLY if the space is not enough to contain all the new values of sub-pointers.

----

The class itself uses malloc, but the user of the class must use only new/delete to manage ImgVec class.

However I agree when you say a thing like "avoid using malloc/realloc/free on C++ becouse it isn't able to call constructors/destructors".

-----

Final Note:

My English is very bad, so I want to say that I'm not flaming nor I'm trying to be rude, but only to explain my point-of-view, so I'm sorry if I'll use a wrong way to explain my opinion...
Last edited on Jan 19, 2009 at 7:23pm
Jan 19, 2009 at 10:31pm
Zaita is correct.

Every malloc() call can be replaced by an equivalent new.

It does not matter how the library uses the memory; vector's specification is such that it is functionally equivalent to an array to the user.

vector<> uses malloc and free because of its requirements. new and malloc differ only in that new also runs the constructor. vector<> does NOT want to run constructors in the case you mentioned; hence it MUST use malloc.

Jan 20, 2009 at 12:11am
I'm sorry... You will surely think that I'm a stupid but... I don't understand what you have said.

Every malloc() call can be replaced by an equivalent new

Sure, true. Nothing to say about it.
But there are no perfect equivalent for realloc. The problem is always this one.
vector<> can be used to manage "arrays" that require to be resized.
I don't understand (your worlds confused me) if vector<> calls constructor if I use a class (live vector<ClassA>). Since now I thinked so.

However. Seeing the fact that BITMAP * objects MUST be inizialized with load_bitmap (or create_bitmap) and then must destroyed with destroy_bitmap, using vector<> directly, is not a solution (need more specific functions, need to set the Allegro functions required to copy an "Image" to a "vector", I need to destroy contained images correctly with destroy_bitmap). So I had the idea of creating a custom "vector", a class, called ImgVec.
I wanted to create a personal "container" (ImgVec) that can contain Allegro Images, can be resized with its own functions (AddImage, AddImgVec, RemoveImage), can call a copy of an image choosed from list (img(ID)) to another pointer, can destroy all bitmap correctly when ImgVec deleted (destructor calls destroy_bitmap function for every BITMAP * and only after that calls free for BITMAP ** with free(Image) ).

So the true "problem" is only the pointer of pointer (BITMAP **) that must be resizable. So the better solution seems to me to use malloc/realloc/free (can resize, I avoid to use useless data that costs space, I need only reallocation and for this reason vector<> seem not so necessary).

Did I do some mistake?

It does not matter how the library uses the memory; vector's specification is such that it is functionally equivalent to an array to the user.

Ok. I think to have understanded this (more or less).
However, thinking about this specific enviroment, I don't need all the "functions" of a vector. Also using malloc I can create "arrays". Surely "vector" will require memory to have access to its own functions that, at the end, will be no accessible thinking about the fact that the BITMAP "array" of my class must be private. I have also my own functions for count(), add(), remove() so I'll have an useless "duplication" if I use vector<>. So, in this case, it seems to me not so efficent to use vector<>.

But, perhaps I'm wrong...

vector<> uses malloc and free because of its requirements

More or less is the same for my class (surely I cannot compare my little class with the power of stl containers).

new and malloc differ only in that new also runs the constructor

Ok. But I uses malloc for a pointer of pointer of a struct (so NO constructors to be worried about)


vector<> does NOT want to run constructors in the case you mentioned; hence it MUST use malloc.

This last think confuses me. I didn't understand it (perhaps becouse of my bad English), sorry

-----

Zaita is correct.

I know that Zaita is an expert (unlike me).
However I only try to demonstrate (with some WANTED exaggerations) that it is not so true that in C++ is SO FORBIDDEN to use malloc/realloc (becouse also vectors<> use them and becouse also some libraries used both in C, C++ can use them). Yes, it is a risk to use malloc/realloc/free becouse are not so raccomended in C++ becouse its object-oriented approach (unlike C). But, perhaps becouse I'm not an expert, I cannot see any problem to use malloc/realloc/free also in C++ if used consciously.
Last edited on Jan 20, 2009 at 12:23am
Jan 20, 2009 at 1:49am
It's not that it is forbidden to use malloc and free in C++.

Zaita's point is that vector<> will do everything you need without you having to worry about the implementation details. Why reinvent vector? You have not demonstrated a reason why vector<> cannot be used.

Simple example. You could use malloc/realloc/free to implement a dynamically sizable array of integers. But a vector of ints does the same thing for you and is much easier to use and get right.

To add an integer to the end of a dynamically resizable array you have to:

1
2
3
4
5
6
int* pArray;   // Assume this is initialized to your array
int  numElems; // Assume this has the number of elements

pArray = realloc( ... );
pArray[ numElems ] = newValue;
++numElems;


And then you have to worry about calling free() when you're done.

Contrast to vector<int>:

1
2
vector<int> array;  
array.push_back( newValue );  


Done. And you never have to worry about freeing memory when you are done. vector<> internally does the malloc/realloc/free for you.

You can just as well have a vector of BITMAP*, in which case vector manages a list of pointers. It does not manage what the pointers point to.



Jan 20, 2009 at 7:32am
I'm sorry but this is no a point. I don't see any reason to "demonstrate" I need to use my class (that uses malloc) instead of vector<>. I think that programming styles and the reasons of chooses made by a programmer is strictly personal and can be the result of a long reflection.
Suggestions by expert persons like all of you are always appreciated and wanted, but there are situations that a person, knowing all implication of a choose and knowing its own skills and attitudes, can manage in his own way.

So... the reason of my first question was born by a doubt that came to my mind and that Zaita, kindly, explained to me. Any other reaply is talking about styles or way-to-do

Saying that I can "demonstrate" why I need this class (and, first of all, becouse I can manage better this way, seeing my "knowledges").
As you said I can also create a vector of BITMAP * but I have, BEFORE (or after) ADDING to vector the BITMAP *, to be sure that BITMAP pointer points to an existing image.
To do this I must load (or "create") an image and, if I want that my vector<> contains "clones" of Image created/loaded (NOT the original ones) I must use also other Allegro functions like blit().

With a classic vector<> (without my class) I need to write, EVERY TIME before adding image clone a piece of code. And, also, unlike your example, is not so clear for me how to manage it correctly with my situation, where original pointers will be deleted after the "vector<>" of Imags are created. (malloc way is clearer for me, in this situation).

My class, instead, do all work, after resizing BITMAP ** with realloc, initialize itself every BITMAP * pointer with create_bitmap and copy itself the src BITMAP * with blit() (so if I deleted src BITMAP * this will have no dangerous effect in my "vector"). And, also, my class will delete itself every BITMAP * in "array" with destroy_bitmap when remove() called or ImgVec is deleted.

But, first of all, ONLY with ImgVec I can use another function made by me called

ImgVec * getImgVec_from_masterimage (BITMAP * src, int xframes, int yframes, int size_x, int size_y);

(A function that can cut an original images into pieces of the same size and save them as a ImgVec - list of Images - that can be also added to another ImgVec with ImgVec->AddImgVec)

If I used vector<> instead of my custom class, I could only add BITMAP* to an existing vector and I couldn't find a way to create a new vector<> "virtually" on runtime.

So, I don't see any reason to make the same thing in a more (for me) complex way and to spend more time when I can do efficently the same thing in a short time (the uses of malloc/realloc/free is not so complex in that class. Malloc is called only once in constructor. Free is called only once in destructor. Realloc is called one time only in any function that need to resize BITMAP ** so one time in AddImage, one time in AddImgVec and one time in both of RemoveImage aliases).

No reason to use vector<> internally into my class for reasons I said before.
Last edited on Jan 20, 2009 at 7:50am
Jan 21, 2009 at 9:45am
to your original question: it is not a problem to mix new and malloc as long as you use the correct function to destroy the allocated memory.

new and delete have the additional functionality to call the constructor and destructor so if you do a free on a "newed" object you are in for trouble and vice versa.

finally i just wanted to add that vector has been designed to be compatible with plain C-arrays, but if you find malloc/realloc works better for you go for it.

cheers.
Jan 22, 2009 at 1:47am
Fair enough.

My point is that I think you are making it harder for yourself by forcing yourself to manage the memory with malloc/realloc/free when vector already does it for you.


Jan 29, 2009 at 5:40pm
However I didn't want to be rude so I am sorry if I was.

----

Another question (this time is about vector<>, becouse I am planning to use vector<> in other different situations than the one showed before).

If I need to create a vector<> of a pointer of a class

1
2
3
4
5
6
7
8
9
Class A {
...

};

int main() {
  vector<A*> array;
  //...
}

If A has a constructor and a destructor, what happens when I add a new A* the constructor and the destructor are called?.
How can I access to the functions of a single class A* contained in vector array?
Last edited on Jan 29, 2009 at 5:42pm
Jan 29, 2009 at 7:51pm
If A has a constructor and a destructor, what happens when I add a new A* the constructor and the destructor are called?.
No. You have to call it yourself: array.push_back(new A());

How can I access to the functions of a single class A* contained in vector array?
array[i]->f();
Jan 29, 2009 at 9:01pm
And then of course you also need to explicitly call delete on the object, since removing from the container will not do that:

1
2
delete array.back();
array.erase( --array.end() );

Jan 29, 2009 at 9:39pm
No pop_back()?
Jan 29, 2009 at 9:45pm
@jsmith: Your code doesn't only deletes 1 element. On purpose?
1
2
delete array.back(); // delete last element
array.erase( --array.end() ); // remove it from the list 


You should use something like:
1
2
3
for (unsigned i = 0; i < array.size(); ++i)
 delete array[i];
array.clear();
Last edited on Jan 29, 2009 at 9:46pm
Jan 30, 2009 at 12:48pm
I was just providing a destructor example to compliment helios' constructor example.

Personally I'd be using shared_ptr or ptr_vector if I had to have a container of pointers anyway.
Jan 30, 2009 at 8:44pm
Thank to all for your explainations.

I'm sorry but I don't know so well STL containers (I learn that they exist thank to this site), so - a part of vector<> - I don't know other containers (also vector<> is not totally clear for me). I'll see if I also find info about shared_ptr and ptr_vector (but, however, it is more or less clear how to do it with stl vector).

I try to make a scheme:

1) Add an element:

array.push_back(new A());

2) Remove last element

1
2
delete array.back(); // delete last element
array.erase( --array.end() ); // remove it from the list  


3) Remove all elements

1
2
3
for (unsigned i = 0; i < array.size(); ++i)
delete array[i];
array.clear();


4) Access to Class functions

array[i]->f()

----

Questions:

1) How to remove from list a specific element (example: element 2) even if it isn't the last one?

2) As someone else asked before... what is the difference from the code posted by Zaita (that uses array.erase() to delete last element) and a code that uses array.pop_back() ?
Jan 30, 2009 at 9:06pm
I can answer both your questions in one shot:
std::vector::erase() can remove from the vector any element.
std::vector::pop_back() always removes the last element, so it's possible to do
[code]
delete array.back();
array.pop_back();
[code]
I.e. It's the exact opposite of push_back().
Jan 31, 2009 at 12:35pm
Clear, but a thing is missing about vector::erase()

If I understood well, I have to pass a vector remainder as a param of erase.

If the element is the last one the remainder is obtained calling array.end (or better --array.end() as I saw in one of the examples showed before by jsmith). But when element is different from the 4 available in vector remainder list?
Pages: 12