Reputation: 275
Here is the situation :
I use a malloc to allocate memory for a struct. The struct contains various items such as pointers, string variables and vectors.
The fact is, when we use malloc, no constructors are called. Using a code similar to the following one, I've experienced some situation where some variables worked while others didn't.
Note : The following code doesn't compile. It's purpose is only to illustrate the situation.
struct MyStruct
{
MyClass* mFirstClass;
bool mBool;
std::string mString;
std::vector<MyClass> mVector;
};
int main()
{
MyStruct* wMyStructure;
wMyStructure = (MyStruct*) malloc (sizeof(MyStruct));
MyClass wMyClassObject;
wMyStructure->mFirstClass = new MyClass();
wMyStructure->mFirstClass->func();
wMyStructure->mBool = false;
wMyStructure->mString = "aString";
wMyStructure->mVector.push_back(wMyClassObject);
return 0;
}
By using pointers instead of those variables (std::string* mString
), followed by a call to the object constructor (mString = new std::string;
) Exception are not thrown.
However, I've experienced a situation where the mString was used without problem without the constructor being called, but when it came to the vector, the application exit automatically.
This left me with many questions:
When will an object throw an exception if no constructor were used?
In the situation I experienced, only the vector caused problem. Could mString be left as it is or should I call it's constructor?
What would be the safest way, using malloc, to do the whole thing?
Upvotes: 6
Views: 14374
Reputation: 92231
1 ) When will an object throw an exception if no constructor were used ?
If you don't call the constructor, there is no object. You have just allocated some space.
2 ) In the situation I experienced, only the vector caused problem. Could mString be left as it is or should I call it's constructor ?
This is all undefined behavior, just about anything could happen. There are no rules.
3 ) What would be the safest way, using malloc, to do the whole thing ?
The safest way would be not to use malloc, but allocate using new
that will call constructors. It is as simple as this
MyStruct* wMyStructure = new MyStruct;
Upvotes: 2
Reputation: 476980
Your code causes undefined behaviour, because your wMyStructure
does not point to an object, so you may not use the accessor operator ->
on it.
An object only commences its life after its constructor has completed. Since you don't call any constructor, you do not have an object.
(If your struct were a POD, i.e. just consisting of primitive types and PODs, then this would be OK, because PODs have trivial constructors, which do nothing.)
The concrete problem you're facing is that the string and vector members of your struct didn't get to call their constructors, so those members don't exists, and hence the entire object doesn't.
If you want to decouple memory management from object construction, you can use placement syntax:
// get some memory
char arena[HUGE_VAL];
void * morespace = malloc(HUGE_VAL);
// construct some objects
MyClass * px = new (arena + 2000) MyClass; // default constructor
YourClass * py = new (morespace + 5000) YourClass(1, -.5, 'x'); // non-default constructor
(You have to destroy those objects manually, px->~MyClass();
etc., when you're done with them.)
Upvotes: 4
Reputation: 146910
It is undefined behaviour to use a non-initialized object. Exception may be thrown at any time- or not at all.
Upvotes: 1
Reputation: 35584
Using object without constructing it must be an undefined behaviour. Anything may happen at any moment. If you do this, you must not rely on any part of your code to run smoothly, because the language doesn't guarantee anything in this case.
Upvotes: 5