Why the ctor and dtor are not getting invoked even though the memory is allocated or freed? What is actually happening here? Please share your thoughts.
#include<iostream>
#include<stdlib.h>
using namespace std;
class a{
public:
int i;
a() {cout<<"\n a ctor \n";}
~a(){cout<<"\n a dtor \n";}
};
main() {
a *ap = NULL;
ap = (a*)malloc(sizeof(a));
ap->i = 11;
cout<<ap->i<<"\n";
cout<<ap<<"\n";
free(ap); //does this actually work? Does this free the memory?
cout<<ap<<"\n";
ap = NULL;
cout<<ap;
}
does the above mean ctor and dtor are not useful or they are just useless?
Everything is ok here.
The constructor/destructor are just normal functions inside.
What malloc does: Reserve xy bytes of memory.
What new does: Call malloc (or something like that), then call the constructor.
Malloc shouldn´t call any constructor (and it can´t,
because it doesn´t know which one. It does know only a byte count).
If you want to handle memory stuff manually and then just call the constructor,
see "placement new"
There's nothing in malloc to trigger calling your descriptor; malloc is not for allocating objects it's for allocating a buffer for general use (and not normally for c++). Since malloc is a C library and knows nothing of C++, it would seem a bit off for it to consider calling a C++ constructor -- especially considering constructors can have arguments and malloc has no way to receive those.
If you have a valid reason to use malloc to allocate what will become an object, you are still responsible for ensuring the constructor and destructor get called. You do that with new and delete but your new call is modified to be a "placement new". it's extremely rare that you will have a legitimate use for this in conjunction with malloc, but its use in your example would be:
void *ap_addr = void*)malloc(sizeof(a));
ap = new(ap_addr)a();
ap->i = 11;
Note that you are now responsible for calling both delete (to get the destructor called), and free() (to release the buffer). Of course, buffer release is optional if you're going to reuse it, for example.
It should be int main
What is the problem of using new>
Do not mix new/malloc with delete/free
use nullptr not NULL
Related
I wrote the following example program but it crashes with segfault. The problem seems to be with using malloc and std::strings in the structure.
#include <iostream>
#include <string>
#include <cstdlib>
struct example {
std::string data;
};
int main() {
example *ex = (example *)malloc(sizeof(*ex));
ex->data = "hello world";
std::cout << ex->data << std::endl;
}
I can't figure out how to make it work. Any ideas if it's even possible to use malloc() and std::strings?
Thanks, Boda Cydo.
You can't malloc a class with non-trivial constructor in C++. What you get from malloc is a block of raw memory, which does not contain a properly constructed object. Any attempts to use that memory as a "real" object will fail.
Instead of malloc-ing object, use new
example *ex = new example;
Your original code can be forced to work with malloc as well, by using the following sequence of steps: malloc raw memory first, construct the object in that raw memory second:
void *ex_raw = malloc(sizeof(example));
example *ex = new(ex_raw) example;
The form of new used above is called "placement new". However, there's no need for all this trickery in your case.
For a class or struct such as your example, the correct answer is use new not malloc() to allocate an instance. Only operator new knows how to call the constructors for the struct and its members. Your problem is caused by the string member not having ever been constructed.
However, there are rare cases where it is important that a particular patch of memory act as if it holds an instance of a class. If you really have such a case, then there is a variation of operator new that permits the location of the object to be specified. This is called a "placement new" and must be used with great care.
void *rawex = malloc(sizeof(example)); // allocate space
example ex = new(rawex) example(); // construct an example in it
ex->data = "hello world"; // use the data field, not no crash
// time passes
ex->~example(); // call the destructor
free(rawex); // free the allocation
By using placement new, you are obligated to provide a region of memory of the correct size and alignment. Not providing the correct size or alignment will cause mysterious things to go wrong. Incorrect alignment is usually quicker to cause a problem but can also be mysterious.
Also, with a placement new, you are taking responsibility for calling the destructor by hand, and depending on the origin of the memory block, releasing it to its owner.
All in all, unless you already know you need a placement new, you almost certainly don't need it. It has legitimate uses, but there are obscure corners of frameworks and not everyday occurrences.
Allocating memory with malloc doesn't call any constructors. Don't mix C-style allocation with C++ objects. They don't play well together. Instead, use the new operator to allocate objects in C++ code:
example *ex = new example;
This is smarter code and will call the std::string::string() constructor to initialize the string, which will fix the segfault you're seeing. And don't forget to delete it when you're done to free the memory and call the appropriate destructors:
delete ex;
The problem is that malloc does not call the constructor of example. Since a string is usually represented as a pointer on the stack, this is set to zero, and you dereference a null pointer. You need to use new instead.
you should not use
example *ex = (example
*)malloc(sizeof(*ex));
because what sizeof(*ex) return is equal to size of long or size of int, which is due to you different compile surrounding.
you can use code as follow:
example *ex = (example
*)malloc(sizeof(example));
I wrote the following example program but it crashes with segfault. The problem seems to be with using malloc and std::strings in the structure.
#include <iostream>
#include <string>
#include <cstdlib>
struct example {
std::string data;
};
int main() {
example *ex = (example *)malloc(sizeof(*ex));
ex->data = "hello world";
std::cout << ex->data << std::endl;
}
I can't figure out how to make it work. Any ideas if it's even possible to use malloc() and std::strings?
Thanks, Boda Cydo.
You can't malloc a class with non-trivial constructor in C++. What you get from malloc is a block of raw memory, which does not contain a properly constructed object. Any attempts to use that memory as a "real" object will fail.
Instead of malloc-ing object, use new
example *ex = new example;
Your original code can be forced to work with malloc as well, by using the following sequence of steps: malloc raw memory first, construct the object in that raw memory second:
void *ex_raw = malloc(sizeof(example));
example *ex = new(ex_raw) example;
The form of new used above is called "placement new". However, there's no need for all this trickery in your case.
For a class or struct such as your example, the correct answer is use new not malloc() to allocate an instance. Only operator new knows how to call the constructors for the struct and its members. Your problem is caused by the string member not having ever been constructed.
However, there are rare cases where it is important that a particular patch of memory act as if it holds an instance of a class. If you really have such a case, then there is a variation of operator new that permits the location of the object to be specified. This is called a "placement new" and must be used with great care.
void *rawex = malloc(sizeof(example)); // allocate space
example ex = new(rawex) example(); // construct an example in it
ex->data = "hello world"; // use the data field, not no crash
// time passes
ex->~example(); // call the destructor
free(rawex); // free the allocation
By using placement new, you are obligated to provide a region of memory of the correct size and alignment. Not providing the correct size or alignment will cause mysterious things to go wrong. Incorrect alignment is usually quicker to cause a problem but can also be mysterious.
Also, with a placement new, you are taking responsibility for calling the destructor by hand, and depending on the origin of the memory block, releasing it to its owner.
All in all, unless you already know you need a placement new, you almost certainly don't need it. It has legitimate uses, but there are obscure corners of frameworks and not everyday occurrences.
Allocating memory with malloc doesn't call any constructors. Don't mix C-style allocation with C++ objects. They don't play well together. Instead, use the new operator to allocate objects in C++ code:
example *ex = new example;
This is smarter code and will call the std::string::string() constructor to initialize the string, which will fix the segfault you're seeing. And don't forget to delete it when you're done to free the memory and call the appropriate destructors:
delete ex;
The problem is that malloc does not call the constructor of example. Since a string is usually represented as a pointer on the stack, this is set to zero, and you dereference a null pointer. You need to use new instead.
you should not use
example *ex = (example
*)malloc(sizeof(*ex));
because what sizeof(*ex) return is equal to size of long or size of int, which is due to you different compile surrounding.
you can use code as follow:
example *ex = (example
*)malloc(sizeof(example));
As such:
class MyClass{
public:
int *property;
MyClass(){
property = (int*)malloc(sizeof(int));
}
~MyClass(){
free(property);
}
};
I understand that there are better ways to do this, but I don't think I understand why exactly this is incorrect.
Would there ever be a reason to initialize a pointer in a constructor with malloc?
At least couple of reasons comes to my mind:
you need to work with C code/library and pass pointer there that expected to be initialized by malloc()
You are limited with resources and want to be able to use realloc() with it
There could be more, but you need to be careful when working with raw pointers, either initialized by new or malloc(). For example your class violates rule of 3/5/0. Best way to handle that - use a smart pointer.
Also you need to remember that with malloc() you need to be sure that memory is properly initialized, it can be done with memset() or simple assignments with POD types or (and this is mandatory for non POD) through placement new. That usage is not trivial so you would want to deal with that when you really need it.
In general you should use new not malloc in c++ code. The only time not to do that is in extreme corner cases where you want to control exact location for some reason, building custom memory pools (and even then you should overload new so as not to call malloc directly in the class definition). In that case you use 'placement new'
The main reason to use new is that it will correctly construct the object that it just made. malloc will return garbage memory. Not relevant (maybe) for ints but certainly important for objects
You have to make sure to disable copy constructor/assignment operator which are generated by default in c++. If you don't, you will have undefined behavior. E.g. Below code will destruct twice.
#include<cstdlib>
static int number_of_constructions = 0;
static int number_of_destructions = 0;
struct S {
int * p;
S() {
p = (int*) malloc(sizeof(int));
number_of_constructions++;
}
~S() {
free(p);
number_of_destructions++;
}
};
void foo() {
S s;
S s2 = s;
}
Link: https://godbolt.org/g/imujg1
Is it possible to zero out the memory of deleted objects in C++? I want to do this to reproduce a coredump in unit test:
//Some member variable of object-b is passed-by-pointer to object-a
//When object-b is deleted, that member variable is also deleted
//In my unit test code, I want to reproduce this
//even if I explicitly call delete on object-b
//accessBMemberVariable should coredump, but it doesn't
//I'm assuming even though object-b is deleted, it's still intact in memory
A *a = new A();
{
B *b = new B(a);
delete b;
}
a->accessBMemberVariable();
You probably should override the delete operator.
Example for the given class B:
class B
{
public:
// your code
...
// override delete
void operator delete(void * p, size_t s)
{
::memset(p, 0, s);
::operator delete(p, s);
}
};
EDIT: Thanks litb for pointing this out.
accessBMemberVariable should coredump, but it doesn't
Nah, why should it? It's quite possible that the memory that b used to occupy is now owned by the CRT, the CRT that your application owns. The CRT may opt to not release memory back to the OS. Core dumps will only happen if you access memory not owned by your application.
Zeroing out the memory occupied by b may not do you any good depending on the type of variable that A has the address of.
My advice would be to allocate B on the stack, that should bring out the fireworks... but then again, not quite in the way you'd expect...
So if you really want a core dump you should use the OS functions to allocate memory and free it:
char *buf = OS_Alloc(sizeof(B));
B *b = new(buf) B();
a->someBMember = &b->myMember;
b->~B();
OS_Free(buf);
a->accessBMemberVariable();
Another poster suggested:
delete b;
memset(b,0,sizeof(B));
Please don't do this!!! Writes to address space that is returned to the memory manager are UNDEFINED!!!!
Even if your compiler and library let you get away with it now, it is bad bad bad. A change in library or platform, or even an update in the compiler will bite you in the ass.
Think of a race condition where you delete b, then some other thread makes an allocation, the memory at b is given out, and then you call memset! Bang, you're dead.
If you must clear the memory (which who cares) zero it out before calling delete.
memset(b,0,sizeof(B));
delete b;
Use placement "new" if you can (http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.10)
and zero out the chunk you gave after calling the object destructor manually.
Use the debugging malloc/new features in your environment.
On MSVC, link with the debug runtime libraries. On FreeBSD, set MALLOC_OPTIONS to have the 'Z' or 'J' flags, as appropriate. On other platforms, read the documentation or substitute in an appropriate allocator with debugging support.
Calling memset() after deletion is just bad on so many levels.
In your example you write
'A->accessBMemberVariable' is this a typo? shouldn't it be 'a->accessBMemberVariable' ?
Assuming it is a typo (otherwise the whole design seems a bit weird).
If you want to verify that 'a' is deleted properly it probably be better to instead change the way you handle the allocation and use auto_ptr's instead. That way you will be sure things are deleted properly:
auto_ptr<A> a( new A );
{
auto_ptr<B> b( new B(a) ); // B takes ownership of 'a', delete at scope exit
}
a->accessBMemberVariable(); // shouldn't do to well.
and a constructor for B in the form of
B( auto_ptr<A>& a ) : m_a(a) {;}
where
auto_ptr<A> m_a
Once you've deleted b you don't really have permission to write over where it was. But you usually can get away with doing just that; and you'll see code where programmers use memset for this.
The approved way to do this, though, would be to call the destructor directly, then write over the memory (with, say, memset) and then call delete on the object. This does require your destructor to be pretty smart because delete is going to call the destructor. So the destructor must realize that the whole object is nothing but 0's and not do anything:
b->~B();
memset(b, 0, sizeof(b));
delete b;
I'm porting a bit of an old code from C to C++. The old code uses object-like semantics, and at one point separates object destruction from freeing the now-unused memory, with stuff happening in between:
Object_Destructor(Object *me) { free(me->member1), free(me->member2) }
ObjectManager_FreeObject(ObjectManager *me, Object *obj) { free(obj) }
Is the above functionality possible in C++ using the standard destructor (~Object) and a subsequent call to delete obj? Or, as I fear, doing that would call the destructor twice?
In the particular case, the operator delete of Object is overridden as well. Is the definition I've read elsewhere ("when operator delete is used, and the object has a destructor, the destructor is always called) correct in the overridden operator case?
The delete operator is used to free memory, it doesn't change whether the destructor is called or not. First the destructor is called, and only after that is the delete operator used to deallocate the memory.
In other words it's not possible to achieve the semantics you're aiming at with C++'s destructors and delete operators.
Sample:
#include <iostream>
#include <new>
using namespace std;
struct foo {
~foo() { cout << "destructor\n"; }
void operator delete(void* p) {
cout << "operator delete (not explicitly calling destructor)\n";
free(p);
cout << "After delete\n";
}
};
int main()
{
void *pv = malloc(sizeof(foo));
foo* pf = new (pv) foo; // use placement new
delete pf;
}
Output:
destructor
operator delete (not explicitly calling destructor)
After delete
Overloaded delete still calls destructor implicitly before it starts executing as opposed to placement delete (but placement delete is not supposed to be called directly).
So if you are going to "delete" object, do not destroy it in advance you will have destructor called twice. However explicit destruction is due if object was created with placement new (but in that case you do not destroy object using delete)
What sort of stuff happens between the destruction of the object and the freeing of the object's memory? If it has nothing to do with the object, then you should be able to delete the object where the destructor appears. If it does, well, I'd examine that very carefully, because it sounds like a bad idea.
If you have to reproduce the semantics, have a member function that releases all the resources, and use that instead of the destruct function. Make sure that function can be called more than once safely, and include it in the C++ destructor just to be sure.
I absolutely don't get why people say it's impossible.
Decoupling initialization from construction and zeroization (tm) from destruction is actually extremely simple.
class Clike
{
public:
Clike() : m_usable(true) {}
void clear(); // performs clean up then sets m_usable to false
~Clike() { if (m_usable) this->clear(); }
private:
bool m_usable;
// real variables
};
Then you can use it like so:
Clike* c = new Clike();
c->clear(); // performs cleanup
// stuff
delete c;
Actually, since destructors should never throw and do not return anything, it is not unusual at all that the cleanup and the destruction be separated so that the cleanup operation may report errors. Especially for complicated beasts like DB Connections etc...
While this is not a 'destructor' thing, it sure works, and so the C-code presented is actually perfectly reproducible without those fancy placement new etc...
You can separate destruction from deletion, but you probably don't really want to.
If you allocate the memory with new char[] or malloc, and then call placement new, then you can separate destruction (which you do by directly calling the destructor) from deletion (or free). But then you're no longer calling the class's overloaded operator delete, instead you're calling delete[] on the char array (or free).
If you call delete via a pointer to your class (the one you overloaded operator delete for), then that class's destructor will be called. So there is no way to separate them in the sense you ask for, of calling delete without the destructor.
No, it is not possible.
delete calls the destructor.
You will need to work out some kind of logic to ensure that Stuff happens in the right order.
Have a look at the std::allocators for the implementation. The answer is 'yes, they may be decoupled'. It's quite easy to do, it just not seen very often.
It sounds like you might want a placement new. On the other hand, it also sounds like your code is getting pretty hairy. It might be time for some heavy refactoring.
The destructor is coupled to delete and you can't call it twice because you can't explicitely call the destructor (or at least it is highly unusual and uncommon, I've never seen it).
However, just make object_destructor() a member function and call it explicitely (and usually it's good style to make it safe for being called twice. In your case however, calling twice is okay anyway, because calling free() with a NULL pointer is legal, so the alternate version of object_destructor is just to highlight how it could be done.
CLASS A {
object_destructor() { free(this->member1); free(this->member2); }
alternate_version_of_object_destructor() {
if (this->member1) { free(this->member1); this->member1= NULL; }
if (this->member2) { free(this->member2); this->member2= NULL; } }
~A() { /* do nothing or just call this->object_destructor() for safety */ }
}
foo() {
A *pa= new A;
pa->object_destructor(); /* member cleanup */
delete pa; /* free object memory */
}