Thread: How bad is it to use alloca()?

  1. #1
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665

    How bad is it to use alloca()?

    So, let's say I have some code that's pretty fast. The only problem is, it uses the STL more than it should and dynamic memory so using multiple threads of the same code causes it to be pretty ridiculously slow.

    What if I used alloca to handle variable length arrays on the stack because it's so much faster? Is this bad?

    I'm probably going to try it anyway (just to try it, because I've never done it and I won't learn anything if I don't) but I'm just curious, is using alloca acceptable? It's just like malloc() but with the much harsher potential to crash your code.

    I'm aware that it theoretically can ruin code but we'll see, I like playing with fire.

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    The stack is limited in size. The stack of a thread is even smaller.

    alloca() is a holdover from a time when people liked tricks. But that's all it is: a trick. If you like it for its speed, it's simple to implement alloca() style allocator yourself using heap memory. Just allocate a large block from the heap, and do the bookkeeping.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #3
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    That's fair. Hey, how do I write an allocator class to use with std::unordered_set?

    I wanna do what you said, allocate a buffer on the heap and treat it just like a stack. No more of this here malloc() checking the validity of every insertion. I tried looking it up and boy is it daunting.

    I guess I need to start with a constructor and a destructor, right? The constructor should allocate the buffer on the heap (using new()) but I'm sure there must be more to it than that. Do I need to write a specific member function (with a specific name) templated to allocate any class given to it? Like, std::unordered_set calls its allocator which I guess would be just new(), right? How do I make it allocate solely to a buffer I've allocated?

  4. #4
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Using alloca() should be ok (just be sure not to call free(), since it's just allocating from the stack). The advantage of using alloca() is no free or destructor is used.

    If needed, there is usually a compile time option to set the stack size, but I don't know how this works when creating threads. This will reduce dynamic memory overhead, but if the problem is due to cache conflicts between threads, using stack instead of heap isn't going to help much.

  5. #5
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    I know and that scares me but there's only one way to find out...

    Time to yolo this thing head on, am I right?

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by MutantJohn
    I'm aware that it theoretically can ruin code but we'll see, I like playing with fire.
    Use a version control system, if you are not already doing so
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Man, writing a custom allocator class looks daunting O_o

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I believe they simplified it a bit for C++11, though I still don't know how "hard" it is. But maybe you should verify and compare just in case.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by rcgldr View Post
    Using alloca() should be ok
    Quote Originally Posted by MutantJohn View Post
    I know and that scares me but there's only one way to find out...
    At least in the case of Visual Studio, if you run in debug mode, it will detect stack overflow and some stack overwrite errors (it writes a pattern to what should be some unused stack space and verifies it afterwards). You could add some code to display and/or check the memory addresses returned by alloca() to see what is going on. This may require sending the output strings to a single thread that displays this data assuming that std::cout is not re-entrant.
    Last edited by rcgldr; 01-20-2014 at 12:03 PM.

  10. #10
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    To get the auto-release behavior of alloca(), you can use a pair of classes instead of one class. An Allocator class can handle allocating the main buffer and keeping track of where the top of the stack (next allocation) is located. When you request a block of memory, the Allocator can return, not a pointer, but an object, the destructor of which takes care of deallocating the memory. So the usage might look like this:

    Code:
    Allocator myAlloc(1024*1024); // 1 MB buffer
    ..
    ..
    Allocation a = myAlloc.allocate(128); // allocate 128 bytes
    void* buffer = a.get(); // get the pointer to the underlying data
    ..
    // use the buffer for stuff
    ..
    // about to go out of scope. The 'a' object will be destructed and take care of releasing the memory back to the Allocator
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  11. #11
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by brewbuck View Post
    To get the auto-release behavior of alloca(), you can use a pair of classes instead of one class.
    The advantage of auto-release is that an instruction at function return typically restores the stack pointer from the backup pointer (assembler instruction mov esp,ebp), during a function return, so it doesn't matter what size or how many alloca()'s were done, and there's no overhead for auto-release.

  12. #12
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by rcgldr View Post
    The advantage of auto-release is that an instruction at function return typically restores the stack pointer from the backup pointer (assembler instruction mov esp,ebp), during a function return, so it doesn't matter what size or how many alloca()'s were done, and there's no overhead for auto-release.
    True, but given decent compiler optimization, releasing this buffer probably takes only one or two addition instructions as well.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  13. #13
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Not gonna lie though, alloca() finally brings static variable length arrays to C++ and it's awesome. I mean small arrays, like 3 or 4 elements (something that certainly should NOT overflow the stack) but the fact that I finally get some dynamic usage out of it is amazing as std::vector's naturally allocate on the heap which is much slower. It's also nice not having to allocate a separate buffer in the first place.

    Still thinking about that allocator though lol. Maybe I'm just too lazy XD

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Wait until std::dynarray.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    It's a shame it looks like it's not going to be in the C++14 standard. That's lame. I guess alloca() will have to do for now but man, having iterators for that'd be awesome too

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. portable alloca
    By wiglaf in forum C Programming
    Replies: 4
    Last Post: 02-17-2011, 12:34 AM
  2. alloca() function
    By budala in forum C Programming
    Replies: 8
    Last Post: 04-28-2010, 10:09 AM
  3. alloca.h
    By kryptkat in forum C Programming
    Replies: 4
    Last Post: 11-15-2009, 12:34 PM