3
class MyString
{
  public:
  MyString(int length):_ptr(alloca(length))
  {
  }
  //Copy Constructor, destructor, other member functions.
  private:
  void* _ptr;
};

int main()
{
  MyString str(44);
  return 0;
}

Is it freed at the end of the main function or immediately after constructor is executed? Is it a good idea to have a string class like this if the above code works as expected?

Update:

It looks like the main danger is

  1. StackOverflow
  2. Inlining of Constructor

I think I can take care of StackOverflow by using alloca for small sizes and malloc/free for large sizes. I guess there must be some non-portable compiler specific way to force the compiler to inline.

I am interested because string class is something that is widely used in any c++ project. If I get this right, I am expecting a huge performance gain as most of the allocations go inside stack which would go into heap otherwise. This will be a utility and the end user will not be aware of the internals.

balki
  • 26,394
  • 30
  • 105
  • 151
  • 3
    It depends on the optimization level you selected. It only works when the constructor is inlined. Don't use this. – Hans Passant Nov 02 '11 at 11:37

2 Answers2

5

According to the documentation of alloca, the memory is freed when the caller of alloca returns. So, the memory will be freed at the end of the constructor if the initialiser list is considered as part of the constructor by the compiler, i.e. the stack frame is created before the initialise list is executed. If the stack frame is created after the initialiser list is executed, then the allocated memory will be in the caller of the constructor and so, in this case, the memory is freed at the end of main. I don't know the standard enough to be absolutely certain which way it'll happen.

However, the value of ptr will be unchanged whenever the memory is finally freed.

Skizz
  • 69,698
  • 10
  • 71
  • 108
  • 1
    +1 I believe that the *initializer list* is processed within the constructor's stack frame, as it might be in a different translation unit and the compiler could not possibly know that it had to allocate extra space *before* calling the constructor. – David Rodríguez - dribeas Nov 02 '11 at 11:56
  • @David Rodríguez - dribeas: absolutely. At least from the implementation perspective the initializer's construction code is executed within the scope of the parent c'tor – valdo Nov 02 '11 at 12:18
3

Definitely the initialization of the class members are executed as a part of the c'tor. So, at least by standard, the validity of the pointer returned by alloca is limited to the c'tor.

So it seems a really bad idea to initialize your class members the way you do.

OTOH there will be no problem with the following:

class MyString
{
  public:
  MyString(void* ptr):_ptr(ptr)
  {
  }
  //Copy Constructor, destructor, other member functions.
  private:
  void* _ptr;
};

int main()
{
  MyString str(alloca(44));
  return 0;
}
valdo
  • 12,632
  • 2
  • 37
  • 67