Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Malloc on a struct containing a std::vector

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:

  1. When will an object throw an exception if no constructor were used?

  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?

  3. What would be the safest way, using malloc, to do the whole thing?

like image 932
Sim Avatar asked Dec 27 '22 15:12

Sim


2 Answers

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.

like image 135
Vlad Avatar answered Jan 08 '23 00:01

Vlad


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.)

like image 21
Kerrek SB Avatar answered Jan 08 '23 01:01

Kerrek SB