Abstract:
alloca is useful for small arrays or strings, but can be dangerous if the array is larger than you expected.

Created by Peter Kankowski
Last changed
Filed under Win32 programming

Share on social sitesReddit Digg Delicious Buzz Facebook Twitter

The perils of alloca function

The difference between alloca and malloc is that memory is allocated on the stack instead of heap. The stack memory is automatically freed when you leave the function.

Stack allocation is much faster: your program just decrements the stack pointer and probes the allocated memory. The program stack is reused for other functions, so it's often contained in L1 or L2 cache, which makes this method even more effective. For these reasons, Agner Fog recommends using alloca for dynamic arrays and strings.

The limit on stack size

However, the maximum stack size is limited. By default, the limit is 1 MB in MSVC++ and 2 MB in GCC; you can increase it with /STACK linker option in MSVC++ or --stack in GCC (MinGW). The limit is stored in exe file headers (SizeOfStackReserve field of IMAGE_OPTIONAL_HEADER).

If you use alloca for user-supplied strings, and the user enters something very long, your program will crash with a "stack overflow" exception. Especially dangerous is calling alloca in a recursive function or a deeply nested function. The stack is also used for local variables (including fixed-length arrays) and return addresses, so the limit is lower than 1-2 MB of allocated data.

Here is a simple recursive program that crashes under both GCC 4 and MSVC++ 2005:

#include <malloc.h>

int OverflowMyStack(int start) {
    if (start == 0)
        return 0;

    char * p = (char *)_alloca(4096);
    *p = '0';
    return OverflowMyStack(start - 1);
}

int main () {
    return OverflowMyStack(512);
}

Solutions

Recent versions of MSVC++ contain _malloca function, which allocates memory on stack if less than 1 KB is requested, and uses heap otherwise. The function is really a macro that calls alloca or malloc depending on the requested size. You should call _freea from the same function to free the allocated memory.

If you use GCC or an earlier version of MSVC++, you can implement a similar macro yourself.

Conclusion

Using alloca, you can make your programs much faster, but you should consider its limitations to prevent the stack overflow bug. If malloca is available, use it. Beware of alloca in recursive functions.

Related articles

Dynamic arrays in C

Peter Kankowski
Peter Kankowski

About the author

Peter is the developer of Aba Search and Replace, a tool for replacing text in multiple files. He likes to program in C with a bit of C++, also in x86 assembly language, Python, and PHP.

Created by Peter Kankowski
Last changed

27 comments

Dmitry Kostjuchenko,

For 'maloca' it is possible to implement similar portable behavior for any platform/compiler using C++ template mechanism:

#ifdef _DEBUG
    #define COMPOSITE_ALLOC_DEBUG
    #include <assert.h>
#endif
 
template <size_t _StaticSize> class composite_allocator
{
#ifdef COMPOSITE_ALLOC_DEBUG
    enum { MAGIC_1 = 0xAB, MAGIC_2 = 0xCD, MAGIC_3 = 0xCD, MAGIC_4 = 0xEF, MAGIC_SEG_SIZE = 2, MAGIC_SIZE = MAGIC_SEG_SIZE*2  };
#endif
public:
    //! Constructor, accepts 'size' parameter expressed in number of bytes to be allocated
    explicit composite_allocator(size_t size)
    {
        // allocate memory
        _allocate(size);
    }
    //! Constructor, accepts 'size' parameter expressed in number of bytes to be allocated 
    //! and 'fill' parameter that used to be filled in every allocated byte
    explicit composite_allocator(size_t size, unsigned char fill)
    {
        // allocate memory
        _allocate(size);
        // fill memory block
        if (m_ptr)
            memset(m_ptr, fill, size);
    }
    ~composite_allocator()
    {
#ifdef COMPOSITE_ALLOC_DEBUG
        // check magic marks' health
        m_ptr -= MAGIC_SEG_SIZE;
        assert(
            m_ptr[0] == MAGIC_1 && 
            m_ptr[1] == MAGIC_2 && 
            m_ptr[m_size + MAGIC_SEG_SIZE] == MAGIC_3 &&
            m_ptr[m_size + MAGIC_SEG_SIZE + 1] == MAGIC_4
            && "<composite_allocator> memory corruption detected.");
#endif
        // release dynamic memory
        if (m_ptr != m_static_pool)
            free(m_ptr);
    }
 
    //! returns memory block associated with this allocator
#ifndef COMPOSITE_ALLOC_IMLICIT_CAST
    operator void *() { return m_ptr; }
#else
    template <class _TyTo> operator _TyTo *() { return (_TyTo *)m_ptr; }
#endif
 
private:
 
    //! selects memory
    void *_allocate(size_t size)
    {
        if (size > _StaticSize)
        {
#ifdef COMPOSITE_ALLOC_DEBUG
            m_ptr = (unsigned char *)malloc(size + MAGIC_SIZE); // allocate MAGIC_SIZE bytes for magic marks
#else
            m_ptr = (unsigned char *)malloc(size);
#endif
        }
        else
        {
            m_ptr = m_static_pool;
        }
#ifdef COMPOSITE_ALLOC_DEBUG
        // set size for debugging in destructor
        m_size = size;
        // mark memory block with magic marks (tail and beginning)
        m_ptr[0] = MAGIC_1;
        m_ptr[1] = MAGIC_2;
        m_ptr[m_size + MAGIC_SEG_SIZE] = MAGIC_3;
        m_ptr[m_size + MAGIC_SEG_SIZE + 1] = MAGIC_4;
        return (m_ptr += MAGIC_SEG_SIZE);
#else
        return m_ptr;
#endif
    }
 
    //! private constructor, makes class instance non-copyable
    composite_allocator(const composite_allocator &);
 
    //! private copy operator, makes class instance non-copyable
    const composite_allocator &operator=(const composite_allocator &);    
 
    unsigned char *m_ptr;                           //!< pointer to active memory block
 
#ifndef COMPOSITE_ALLOC_DEBUG
    unsigned char m_static_pool[ _StaticSize ];     //!< static buffer
#else
    unsigned char m_static_pool[ _StaticSize + MAGIC_SIZE ]; //!< static buffer + MAGIC_SIZE bytes for control marks
    size_t m_size;                                    //!< allocated size
#endif
};

this can be used as:

 
// allocating 256 bytes for string on stack
{
    composite_allocator<1024> __memory(256);
    char *buf = (char *)((void *)__memory);
}
 
// allocating 4096 bytes for string from dynamic memory (non-stack)
{
    composite_allocator<1024> __memory(4096);
    char *buf = (char *)((void *)__memory);
}
 
// allocating unknown number of bytes for string from dynamic or static memory, depending on 'my_size' 
// if <= 1024 - then static, or dynamic if >
{
    size_t my_random_size = rand() % 8192;
    composite_allocator<1024> __memory(my_random_size);
    char *buf = (char *)((void *)__memory);
}

This approach does not provide same schemantics as malloca e.g. as calling method but still is ok for a number of tasks where memory is allocated within a scope of code execution, it also behaives in auto-free manner.

Advantages: 
 - portability
 - additional debugging capability
Drawbacks: 
 - on-stack size is hardcoded by template parameter and can waste unused stack memory
Peter Kankowski,

Thank you. Note that the class always allocates a fixed amount of stack memory (_StaticSize), so it typically uses more stack memory than malloca.

ace,

See also "Thread Stack Size": http://msdn.microsoft.com/en-us/library/ms686774(VS.85).aspx If you make threads, every one will also take the same size as in SizeOfStackReserve unless you take care to select another size.

Dmitry Kostjuchenko,

Yes, actually drawback of such class-based allocator that it allocates fixed ammount on-stack specified by templ. parameter (not by parameter in constructor) which might not be used later on, like in my example application could use only 256 bytes, so we can say we loose size but win speed and portability. Corrected my post to mention this drawback.

ace,

I don't like the class and I don't like the usage examples. If I understand correctly,

composite_allocator<1024> __memory(256);

means "I know I'll use 256 but I'll spend 1024 bytes"?! And

char *buf = (char *)((void *)__memory);

means "I'm making 'clever' templates but I'm not capable making them to be used without explicit casts every time." Argh. That code would never pass some code review.

Peter Kankowski,

Here is some information about malloca in MSVC. It's implemented as a preprocessor macro (see malloc.h in include directory). Before the memory block, it puts a marker to distinguish between the memory allocated on stack and on heap; freea uses this marker to decide if it should call free() on the block. In debug version, memory is always allocated on heap (to use debug heap checking).

Unfortunately, you cannot wrap alloca call in a class, because it must be called from the function that allocates the memory. That's why malloca is a preprocessor macro. In Dmitry's class, I like the auto-free behavior, which cannot be implemented with a macro.

Dmitry Kostjuchenko,

[Ace] I did propose a possible portable way of implementing malloca without depending on any compiler's API, if you have anything better to propose go ahead, but blaiming somebody's work does not make you smart, I did not make my proposal just for you to like it. The class is for demonstative purpose only to show/propose how malloca can be emulated in compiler independent way. You can extend, modify, make it more convenient to use in any way you want, the basic idea is laid out.

My examples are ok if you have anough knowledge about possible situations (I guess you are not really understanding what I wanted to show by examples) with memory allocation, one of them (less syntetic than that one with 256 bytes which you sadily disliked) would be:

std::string fmtstrc(const char *fmt, ...)
{
    va_list arg;
    va_start(arg, fmt);
 
    size_t size = vcprintf(fmt, arg);
 
    composite_allocator<1024> __memory(size+1); // allocate on stack or dynamically
    char *buf = (char *)((void *)__memory);
 
    vsnprintf(buf, size, fmt, arg);
    buf[ size ] = 0; // we can manually terminate, or use composite_allocator with __memory(size+1, 0)
 
    va_end(arg);
 
    return std::string(buf);
}

Here we asssume that in most cases our formatted string would be with 1024 bytes length, but we are not limited to this fixed size and allocator will allocate any bigger size with malloc. If such formatting happens often then we save time on memory allocations as we use static stack memory. If such formatting happens from different threads and string is normally less than 1024 bytes then we can win even more performance depending on malloc implementation if malloc is not multithread optimised. This more live example shows that we speak about allocations with not predefined size but guessing possible behviour.

Of course you can throw away this class and use malloca if your compiler has it like

char *buf = (char *)malloca(size+1);
// later in code
freea(buf);

but it is less portable, or use ifs

char static_buf[1024] = { 0 };
char *buf = static_buf;
if (size > 1023)
    buf = malloc(size+1);
 
// later in code on exit
if (buf != static_buf)
    free(buf);

but it is more messy.

Using a class with automatic services is producing much safer and cleaner code. It is much convenient to use in many places all over the app code rather than combat with a lot of checks.

Cast to void* says to every skilled developer - I am explicitly getting a pointer to memory address and casting it to my needed type. This is much better to evaluate code as you clearly see casts and cleary understand why they were done. I guess you ment that instead of void * cast operator I would need to use

template <class _TyTo> operator _TyTo *() { return (_TyTo *)m_ptr; }

but it was my explicit intention as I explained earlier, that char *buf = _memory; is less informative than char *buf = (char *)((void *)_memory), at least to me, and programmer will have no other way to get it compiled :) I advise not to blaim a things you are not aware of or which you do not get.

Anyway taking into account criticism I will update my first post :)

ace,
I advise not to blaim a things you are not aware of or which you do not get.

I'd make the class which I'd like to be used this way for unknown n:

MyAlloc< char, 200 > a;
char* buff = a.alloc( n );

but for the case where I know I need 256 chars I'd just use:

char buff[ 256 ];

and not

MyAlloc< char, 1024 > a;
char* buff = a.alloc( 256 );

and certainly I would never use:

char *buf = (char *)((void *)__memory); // very ugly

and especially not

composite_allocator<1024> __memory(256); // wrong
char *buf = (char *)((void *)__memory);  // very ugly
Dmitry Kostjuchenko,

If you like another way of making same thing it is ok. I did not want anyone to like my sintax or the way I use and make classes, the idea was to provide malloca analogue as an addtion to Peter's post. The code I presented is fully correct and valid and I will again exlain why:

"I'd make the class which I'd like to be used this way for unknown n" What is a problem to provide this 'unknown n' to a constructor as 'composite_allocator<200> _memory(n);' I do not get you at all, sorry :)

what is wrong with

composite_allocator<1024> __memory(256); // wrong
char *buf = (char *)((void *)__memory);  // very ugly

??? Please provide arguments and why it dos not work.

We did not speak about char buff[ 256 ]; it was not a point of discussion at all, buff[256] - is just static on-stack memory chunk without a possibility to extend it if needed during runtime, please provide arguments what is connection to malloca behaviour with it or your point is failed.

I would put your example to make as mine

MyAlloc< char, 1024 > a;
char* buff = a.alloc( 256 );
 
equals to:
 
composite_allocator<1024> __memory(256);
char* buff = __memory; // COMPOSITE_ALLOC_IMLICIT_CAST is defined before class declaration
 
why it is wrong? both examples do exactly the same thing.

it just redocarates my example and does not change anything at all, your point is again failed. Moreover you bind template class to a type, I do not bind it because I do not like it to, so it is just a matter of perception and how you are using it in code further. I also did not want to pollute template parameters with any type as it may mislead programmer when he would percieve construction as MyAlloc< char, 200 > as: allocate 200 units of char, or MyAlloc< int, 200 > - allocate 200 units of int, as such construction looks very much similar as static array declaration. I intentially decided not do like that to avoid such situation, more over: MyAlloc< void, 200 > – looks very ugly to me. Cast operator (void *) of composite_allocator indicates that allocator is not bound to any type and just provides an address of anonymous memory block, just like malloc does.

You allocate dynamic memory in .alloc call while static memory is already allocated by compiler, while I intentionally did it in constructor just to have memory selected or allocated in constructor and represent an instance of a class as imaginary memory block with no possibility for user to allocate anything else by mistake 2-nd time for example. Your implementation exposes this possible bug to user and through .alloc call it is possible to try to allocate memory while it was already allocated that will lead or to memory corruption (static-dynamic mix) or to memory leak as this class is supposed to deallocate dynamic memory in destructor. That is why 'void *_allocate(size_t size)' is private in composite_allocator.

Ace, non of your examples showed to me or convinced me why I shall like your class implementation and behavior more than mine and why your examples are more correct than mine. You did not put any explanation and moreover you misunderstand the functionality that I was implementing and why I did it.

I decided to extend a class with debugging capabilities that expand its usage not only to on-stack allocation but also provide malloca #define functionality under debug build where memory is allocated with debug_malloc and its bounds are controlled. See my first post.

ace,
I would put your example to make as mine

I didn't make such example and I never wouldn't. When I know that I need 256 I'd never write "use some unnecessary class to reserve 1024, use 256 from that."

such construction looks very much similar as static array declaration.

It actually is a local array in your class too.

I intentially decided not do like that to avoid such situation

To confuse anybody else who's reading?

I intentionally did it in constructor just to have memory selected

As far as I understamd, no memory is not selected, it is allocated from the stack whenever you declare an object of your class.

You did not put any explanation

In my first post: a) an example which does what is fully not needed is a wrong example. b) casts are ugly. Of course, if you say that you like them, I can't say anything against such argument except what I already said: your code wouldn't pass a competent code review.

I forgot until now: naming your class in a way that it looks too much like a part of the language which additionally confuses causal reader ("when was that added to the language? what does it do?") would also not pass the good review.

Dmitry Kostjuchenko,

Ace, I did not put my code here for just your personal review :) Your arguments are all senseless and do not proove in any way why my implementation is worse than your. You also do not get the whole idea of this allocator, thus it seems like we speak on different languages.

1) Your proposal exposes such class to a very likely misuse by a programmer that would lead to a memory corruption (stack or dynamic) or dynamic memory leaks:

{
    MyAlloc< char, 1024 > a;
    char* buff = a.alloc( 256 );
 
    // somewhere later within same scope
    {
        int *array = (int *)a.alloc(2 * sizeof(int)); // no leak, ok, still within static memory range, but already a misusage
 
        // somewhere again
        {
            buff = a.alloc(2048); // !!! allocating dynamic memory, 3-rd allocation attempt already !!!
        }
 
        stuct A { int c; };
 
        A *my_a = (A *)a.alloc(sizeof(A)); // hello, we leaked memory if alloc just provides pointer to own static block or does malloc instead, 4-th allocation, my god
    }
}

this trivial example shows how bad is an initial design of such class you proposed. .alloc makes it possible to call it as many times as you want and do whatever coder wants, all will be successfuly compiled. In this sense you must provide also manual .free method to make user call it after each .alloc but this just adds additional unneded methods and makes implementation unoptimal and heavy with many checks.

'composite_allocator' has .alloc analogue as private class member which is called in constructor only once! thus noone can exploit and misuse the class as constructor will be called only once per calling thread. This is an obvious secure implementation I guess you shall understand this.

2) Cast operator (void *) or through template parameter to a needed type - I just like to do so, or you can change it to something void *get() or template<class T> T *get() { (T*)ptr; } it does not change the behaviour and design of the class when I try to maintain 1 call for allocation only. It must be getter but not any method that might allocate something like .alloc in your proposal or change allocator's internal state.

3) Memory allocator must not be bound to a type as you can use it within a scope to represent different objects of a different type, thus MyAlloc<TYPE, STATIC_SIZE> is completey wrong and is a bad design. Yes memory is actually represented in form of array of bits and bytes and thus I express it in form of char or uchar, but representing it diffferent types like you proposed is fully misleading. For array MyAlloc<TYPE, STATIC_SIZE> is ok, for universal memory allocator - not.

5) "As far as I understamd, no memory is not selected, it is allocated from the stack whenever you declare an object of your class. " You are not correct, memory is allocated via malloc or by providing pointer to a static byte array of a class depending on allocation size requested. For safety sake I chose to do such allocation only once through constructor of the class to avoid any other extra checks and misusage.

6) I will also break your point about how char buff[256]; can be bad even in its trivial form of usage:

 
    // example 1:
    {
        char buff[13];
        strcpy(buff, "My Corruption"); // we corrupted 1 byte of stack memory in the tail
    }
 
    // example 2:
    {
        composite_allocator<32> buff(strlen("My Corruption"));
        strcpy(buff, "My Corruption"); // we "corrupted" 1 byte of stack memory in the tail
    }

in example (1) under Debug some compiler will detect that stack memory was overwritten, some not, in Release compile will never detect or signal about it but will lead to just misterious bugs and crashes. in example (2) when COMPOSITE_ALLOC_DEBUG is defined 'composite_allocator' will check memory block guarding marks in its tail or start and will signalise/assert and etc, whatever programmer changes such behaviour to (in my implementation I do assert). if assert is provided that also triggers under Release build, you will always have a control over such situation. Such memory corruption problems exist everywere in many projects especially with >1 coder, 'composite_allocator' will combat with these troubles automatically :)

So the myth that char buff[256]; is absolutely better than composite_allocator<256> buff; is also disproved from the view of production of maximally secure code.

Please argue if you can, you are welcome :) I like our discussion very much that led to extention of allocator with memory debugging capability.

ace,
It seems like we speak on different languages.

Yes, we speak different languages. I just can't parse your last post. Everything is so mixed up. It's impossible to argue on relevant subjects because you made as much as you could to obscure them in confusion. In your last posts there are your attempts to prove your point using something I never wrote and with the code I don't approve anyway. Then you attempt to introduce something new but still mixed up. On one place you talk about "universal memory allocator" relating to your class, on another you "allocate in the constructor only once" (what's universal with that?) and then access that "memory" by casing and recasting. It's really so mixed up that I don't know what I can discuss.

I still don't understand why you insist on your use of:

composite_allocator<1024> __memory(256); // ?!?

and equivalents? Don't you see how absurd it is? I really read "in my language" that single line as: "I don't have any idea what I'm doing. I named the class in a way to confuse the reader. I wrote it to be able to use memory from stack and then I'm using it in a way that's directly against the assumptions for which I wrote the class, reserving 1024 bytes for something I know takes 256." And when you construct your example with the same numbers but with my name of the class it is still absurd and I don't agree with it. It only appears that it has something to do with me when it really doesn't.

Anyway, as soon as you access more than one of something over the pointer you are not "protected" by definition of C and C++. No matter how complex you write some your code instead of simply char buff[ 256 ] it won't make change. You make example where you use strlen with your class and claim advantages brought by your class still you're using for the argument something orthogonal to your class, and I can prove it by not using your class at all:

char buff[ 13 ]; // that what you apparently avoid but you just write the 
                 // equivalent with a lot of unnecessary code
safeStrCpy( buff, sizeof( buff ), szSomething ); // debug easy, strlen implicit
                                                 // and your class not used at all

You should really try to focus on your class and not to try to prove something with something irrelevant. For one more example, you say "if assert is provided that also triggers under Release build." It's nothing in any way related with your class. And in the language definition assert is a macro which expands to nothing in release build (if the _DEBUG would be defined it wouldn't be really "release"). There's so much of confusion in your posts.

Now to few points from all your text that have more sense:

1) I agree it can be sometimes nicer having:

MyAlloc< char, 256 > a( n );

but then of course I don't even need

char* buff = a;

I can just write:

MyAlloc< char, 256 > buff( n );

and use buff in the rest of the code. Then the only conceptual difference to your class is that you'd like not to specify the type there. I'd still prefer it with the type there and without other implicit or explicit casts.

2) "you must provide also manual .free method"

Of course I don't have to. There's no obligation for any code to support every imaginable use. Any code supports only subset of everything imaginable. I like the code to be as simple as possible, and I agree allocating in constructor can be simpler in some scenarios. Still there is a reason I used:

MyAlloc< char, 200 > a;
char* buff = a.alloc( n );

Can you guess it?

Dmitry Kostjuchenko,

1) "I wrote it to be able to use memory from stack and then I'm using it in a way that's directly against the assumptions for which I wrote the class, reserving 1024 bytes for something I know takes 256." I would like to ask you then, did you notice malloc usage in allocation method? The whole class is not to replicate schemantics of 'char my_array[x]' but to provide some automatic mechanism to provide a pointer to a user to a static memory or to a dynamic memory if allocation request goes out of static memory size that was preordered by template parameter. An example with 256 bytes was just a syntetic demonstration that in this case malloc will not be in use, could you get it now at last? Please :) Instead of 256 I put an example with fmtstrc function that deals with unknown number of bytes to be allocated whether statically or dynamically.

2) You violate my example with memory corruption by injecting your 'safeStrCpy', we did not speak about safeStrCpy, strncpy_s and similar methods that provide safer coding practise, I used exactly 'strlen' and wanted it for that example to show how easy you can break an application with those 2 lines. It is obvious and very demonstartive and shows that in exactly same situation (ok, remove strlen from that example) 'composite_allocator' provides memory access control.

3) assert in Release: if you do not use standard library's assert but your own version you can throw exception at any time you want and with any build type, it is absolutely no problem, moreover if your app is compiled with debug data under Windows for example you can get minidump for further code analysis on crash, or using gdb under Linux. So let's not speak about obvious things. In this example I focused exactly on my class that provides memory usage control and gave an example.

4) Going to your points 1 and 2:

- Ok I am glad that you finally got a point that allocating memory once is a good idea and obviously a constructor is a good way of doing this. But again why do you bind to a type? I showed in my examples with your imaginary class that allocated memory could be used/reused for anything, not just char/int and etc. so it shall be void in order not to misguide class user who would think: Why 'char'? what if I put MyAlloc< struct MyStruct, 256 > a( n ); will it allocate 256 items of struct MyStruct or it allocates 256 * sizeof(struct MyStruct)???. Such question will obviously appear and user will have to browse documentation and explanation to your class to find out its behaviour and what exactly it allocates. MyAlloc<256> that later provides (void *) clearly says - I am getting a pointer to a memory block of 256 bytes, as no any types are mixed in declaration. I hope you will finally understand this point.If you took a time to review a class members of 'composite_allocator' instead of just saying I do not like it you would find out that it behaves without additional variables for situation as you showed 'char* buff = a;' as it has:

template <class _TyTo> operator _TyTo *() { return (_TyTo *)m_ptr; } // if COMPOSITE_ALLOC_IMLICIT_CAST is defined

this allows to use a class instance exactly like a variable holding a pointer to allocated/pointed memory:

composite_allocator<32> buff(n*sizeof(wchar_t));
wcsncpy(buff, n, L"Hello!");
wprintf(L"%s, 'composite_allocator' can be used just as variable!", (wchar_t *)buff);

- "Of course I don't have to. There's no obligation for any code to support every imaginable use. " Well, you have to if you write code for not just self-usage and I showed examples how user can easily leak a memory calling n-times your public .alloc(n) mehtod. It is very easy to do and in big projects most likely somebody would do it. I know it very well from my practise, belive me :) One-time allocation and providing just getter is an excelent escape from such possible problem and I used it for 'composite_allocator'. Again, .alloc(n) - does not make code simpler but exposing it to a bugs in application, misuse by programmer, additional reading of its behaviour. Of course you can make .alloc(n) be checking if memory was allocated/selected but this is additional code, and additional reading of documentation for a user again. 'composite_allocator' is well percieved as - one-time allocated memory block with just 1 way to get a pointer to that memory address.

ace,
Instead of 256 I put an example with fmtstrc function

Only you didn't, you used time after time wrong examples.

ok, remove strlen from that example

Now we agree. Thanks.

'composite_allocator' provides memory access control

You're still confusing implementation details with the usage scenarios, which is all I ever discussed. Like "when you buy our vacuum cleaner you'll get with two towels too." Again, char buff[ 256 ] is correct code which certainly doesn't need to be replaced with the constructs you wrote.

if you do not use standard library's assert (…)

Can be done, but is fully irrelevant to the topic.

will it allocate 256 items of struct MyStruct or (…)

Of course, why shouldn't it?

I hope you will finally understand this point.

I understood even before that you can't easily let go of unnecessary code. I just see now that it's still so.

template <class _TyTo> operator _TyTo *

Also fully unnecessary.

how user can easily leak a memory calling n-times your public .alloc(n) mehtod

You haven't answered my last question from the last letter, as far as I can tell? The answer is actually needed in order to discuss .alloc( n ) topic further.

'composite_allocator' is well percieved

IMHO it is clumsy named class, clumsy written and clumsy used, all of which I wouldn't accept to my projects as it is. But I can imagine that it can be accepted to boost lib (which just tells how I value boost!). By the way, have you checked if boost actually has something like that? I can imagine it's then with even more unnecessary things, for good measure. :) Now seriously, you can really try to contribute it there, or publish it to codeguru or whereever – it would be more interesting for you to get more responses than just discussing with me, just one programmer with different taste about good code. Of course, if you ask me, I'd drop unnecessary things and use different name. And except in trivial projects I'd use .alloc( n ) semantics.

Dmitry Kostjuchenko,

Hi Ace, I am not the one who posts a code all over the internet :) to codeguru and etc. to be famous. I just visited Peter's blog an noticed this article about malloca and proposed portable solution which I use for a long time for the case when compiler does not provide malloca and 'composite_allocator' fully complies with this task. How it is named, how parameters organised and etc. it is just a personal choice and a particular way of implementation but the general idea how to do it is provided and shall be understood for the interested person. I disliked your first criticism personally with words: I do not like, I can do it better, when you tried to show how good you are and how wrong all others are without really going indepth into a problem. I did not make it to be liked by the whole world but just was sharing with implementation idea. You proposed wrong solutions and did not get why I did not used that approaches you were advertising. First before pure criticism you had to ask yourself why I:

1) made allocation through constructor only
2) made _allocate(size) call private
3) made getter for an address only (it does not matter how getter is implemented, it is up to personal perception)
4) used no type binding through template parameters

You just trying to advertise what you say without any explanation, just saying - it is better because you proposed. Our discussion may last for ages in this way :) I am sorry. I put all my explanations on a table and have nothing more to add.

ace,
you had to ask yourself why I: 1) made allocation through constructor only

I don't have to ask myself, I know the answer and I already wrote it, you've read it and commented, so you know that I know.

On another side I asked you twice to guess why I wrote public alloc. And you didn't answer.

made _allocate(size) call private

I think that's the same question as your previous.

made getter

I think that what you call getter actually increases the mess.

used no type binding

I already answered that too, it's ugly and unnecessary. The class is used only to possibly use stack for something you always know you actually need in the next line. Then it should create n times that something, not "memory."

I won't write the code, but my actuall class would have declarations like this:

template < class T, size_t maxBytesOnStack > class AcTScopeAlloc
{
public:
    enum { m = maxBytesOnStack/sizeof( T ) };
    AcTScopeAlloc() : used( 0 ), onHeap( 0 ) {}
    T* allocInScope( int n ) {
        // just 4 lines of code here
    }
    ~AcTScopeAlloc() { delete[] onHeap; }
private:
    T  pre[ m ], * onHeap, * used;
    // the following I'd write only if the whole class is public 
    // part of some library, otherwise I'd just not write it:
    template <class S> operator S*() { return 0; }
    AcTScopeAlloc( AcTScopeAlloc& ) {}
    operator=( AcTScopeAlloc& ) {}
};
Dmitry Kostjuchenko,

"why I wrote public alloc. And you didn't answer. " - I actually did answer saying that it is wrong class design and implementation and demonstrated how user can play with it and leak memory if .alloc is not correctly implemented taking into account its multiple possible calls.

As to your phrase "The class is used only to possibly use stack for something you always know you actually need in the next line. Then it should create n times that something, not "memory.", well it depends on what idea you are/were following, if 'malloca' was allocating N objects of some TYPE then I would implemented it like that, but in its original behaviour 'malloca' allocates N bytes, so does 'composite_allocator' - allocating N bytes and no more additional behaviour, it also provides debugging capability similar to 'malloca'.

It is very difficult to discuss looking at just partial prototype, if you could post whole working class it would then be worth comparing the functionality, pros and cons of each solution. For this moment I can't judge and can't compare from your partial implementation. "just 4 lines of code here" - it would be worth seeing them and the rest of the class till its fully operational version. Then we can make stress tests and comparison.

ace,
I actually did answer saying that it is wrong class design

My question was "there is a reason I used it, can you guess it?" You still avoid the answer with your response. Let me give you a hint, it's a real technical reason.

taking into account its multiple possible calls.

That reminds me: you can also use your "allocator", which is "composite" whatever would that mean to the reader, and then pass the pointer outside the scope. So to be safe, it shouldn't exist. On another side, when I use "ScopeAlloc" and allocInScope( n ) I explicitly know at that point how long the result is valid, and I'll know even when I read the code ten years later. Even somebody who never saw anything else but the line where the class is used would know.

Back to the multiple calls argument, calling free or delete multiple times produces problems. So we shouldn't have free and delete functions then?

For this moment I can't judge

For me it's OK if we keep it so.

we can make stress tests

Stress tests? Do you want to again point that the best feature of your class is the "MAGIC" you wrote which should "catch overwrites of markers" for your debugging purposes? The "free two towels with your purchase" argument? No need for "stress", there's no "MAGIC" in my class. It comes from adhering to some principles: I don't "just use" strcpy. I don't cast something to something else, instead I just create what I need. I name the class to make the validity of its use obvious.

In fact, the actual class I really ever use is even simpler:

class ScopeAllocTCHAR
{
    enum { m = 260 };
    TCHAR  pre[ m ], * onHeap;
public:
    ScopeAllocTCHAR() : onHeap( 0 ) {}
    TCHAR* allocInScope( int n ) {
        // just 3 lines of code here, and no magic
    }
    ~ScopeAllocTCHAR() { delete[] onHeap; }
};

It's not template as I don't need that behaviour for other types and there's no passing the size for the stack, I've never found the need to vary it. I wrote the template version in previous post to point that you're misusing casts.

Dmitry Kostjuchenko,

It is also possible to pass pointer obtained from standard 'alloca' out of a scope and run into a problem. Actually by unskilled programmer or just by mistake this can be done at any time. Noone can make it so safe to avoid it at least not in C/C++. In C# it is possible so it is excellent for a dummies.

I will again repeat, it does not matter how do you provide pointer to allocated memory, through cast operator, normal function the idea of the class does not change. Your implementation is also same but differs by requiring to call .alloc while it is done in mine by constructor. It is all just implementation details, who likes what. I also do not like to bind any memory allocator to a type as if it is type based it shall be clearly stated that it is an array of a Type, for me it is much more convenient to split these things like that.

It is a pitty that you do not post complete class implementation and rather change it (your previous and next post). Last example 'ScopeAllocTCHAR' will suffer from accident copy of one instance to another resulting in leaks. So you provide some messy examples that already have bugs. I would prefer to see full implementation so that people who would read our posts could choose one or another.

'ScopeAllocTCHAR' is very limited in performance/usage benefits as 260 bytes would be very low for intensive string operations or some other needs were you use memory for allocating some bigger structs. So I would say I would never use such implementation and std::vector<TCHAR> would be much more convenient to use then :) but it is different story.

'I just create what I need' - it is ok if you work with just one type, but you can also reuse memory for different types and there you will have no other option but to cast into that type. That is why I provided or (void *) operator/getter or auto-cast operator (that is implicit and less visible method).

Well, I would conclude that both implementations can live and can be chosen/implemented depending on programmer preferences. I use my class in a number of C++ libraries succesfully and it serves very well to me in the design implementation which I showed here (thanks to our discussion I also added debugging of memory region that is useful to my view especially when you really must know that everything works ok for critical to reliability applications).

ace,
will suffer from accident copy of one instance (…) that already have bugs

There are no bugs. Unfortunately, you obviously tend to edit the same post many times, so then it's not clear from the discussion what was originally in any of yours. But I still don't like your class. I can't prove it anymore but I think you haven't had private copy constructors before you saw my small (not the smallest) class? Then you claim that I "post bugs" for something I explicitly explain why and where I omit it?

If there were some bug I wouldn't change my old post, I'd admit it and write a new one. But there are no bugs up to now.

is very limited in performance/usage benefits as 260 bytes would be very low for intensive string operations (…) I would say I would never use such implementation and std::vector< TCHAR > would be much more convenient

Any std::vector that I know allocates on heap. Anyway it's OK, you should really use the most concise solution you can find: the less code the better, unless it's on the critical path. Even then, from different possibilities, the smallest effective solution is the best one. That's why I used my class in a few places it really mattered. I know that 260 was the proper size. And I still don't know any practical case where your class with all that in it would be actually needed to solve some real problem and doesn't only increase the amount of unnecessary code.

but you can also reuse memory for different types

I've never needed that. In that almost improbable case I wouldn't refrain from using cast on the spot. But unless it becomes a typical scenario I wouldn't change the class. See above.

That is why I provided or (void *) operator/getter or auto-cast operator

And that's among the reasons I still don't like your class. See all above.

BTW In the meantime I looked at _malloca and I doubt I'll ever use it.

Dmitry Kostjuchenko,
I can't prove it anymore but I think you haven't had private copy constructors before you saw my small (not the smallest) class?

You miss a whole history of our discussion, copy constructor/assignment op. were there before you made a post - 'I don't like the class and I don't like the usage examples.'. I already said that 'composite_allocator' is used in my sub-system libs for a long time (debuuging capab. is only a new future added). ScopeAllocTCHAR is missing them and exposed for copying that I interpret as - serious bug, or you shall post full class implementation if it was partial.

"BTW In the meantime I looked at _malloca and I doubt I'll ever use it. " - this is why you misinterpret functionality 'composite_allocator' as you really never used 'malloca' and do not have an idea for its application. Creating/evaluating something you never used is really a bad idea. Please scroll up and find one of good working example with std::string fmtstrc(const char *fmt, …) function. It can use or 'malloca' or 'composite_allocator'. For 'malloca'/'composite_allocator':

std::string fmtstrc(const char *fmt, ...)
{
    va_list arg;
    va_start(arg, fmt);
 
    size_t size = vcprintf(fmt, arg);
 
#ifdef HAVE_MALLOCA
    void *__memory = malloca(size+1);
#else
    composite_allocator<1024> __memory(size+1); // allocate on stack or dynamically
#endif
    char *buf = (char *)__memory; // COMPOSITE_ALLOC_IMLICIT_CAST is defined
 
    vsnprintf(buf, size, fmt, arg);
    buf[ size ] = 0; // we can manually terminate, or use composite_allocator with __memory(size+1, 0)
 
    va_end(arg);
 
    std::string ret(buf);
#ifdef HAVE_MALLOCA
    freea(__memory);
#else
    return ret;
}
ace,
You miss a whole history of our discussion

Exactly! I miss a history since you're busy faking it. It is never clear when and how you edited which of your old posts (in fact it would be possible to track that with some external effort but it's just not worth). You know, that "edit" feature exists not for you to really change your old posts beyond recognition but to fix spelling or formatting errors. When you change the content, the whole discussion doesn't have sense anymore. That's impolite to others.

exposed for copying that I interpret as - serious bug

You can interpret it so, but in my opinion you're just wrong, I've already said why.

you really never used 'malloca' and do not have an idea for its application

I've never used malloca, but my small class I wrote long ago is already in use in production code for many years. That's one of the reasons I will never use malloca. My opinion about your class is already known: Instead of something that can be small and simple it's something unnecessary complex both on implementation and use side.

Creating/evaluating something you never used is really a bad idea

I could easily say that I don't like it exactly because I already made and used something significantly more elegant.

It can use or 'malloca' or 'composite_allocator'.

I've got an impression that your "example" has a leak when it's used with malloca. So who's "not having idea" then? Of course I wouldn't be surprised if you modify it before I look at the same post the next time, but think how much you can be respected then.

Dmitry Kostjuchenko,

Ace, do not get frustrated, you are inpolitedly trying to say that I correct my posts just to cheat you, I correct posts just to make anyone reading them not to run into problem if one would use pieace of code placed here. I wouldn't advise anyone of using your code as it is incomplete and erronious in design and application and I am surprised that you still argueing. Moreover copy protection of classes is not that cosmic programming technique that only you are aware of it, I am sorry to say but your words and tries to make me a liar are childish. It is a pitty that there is no history of edits so I would proove.

If you are talking about 'ScopeAllocTCHAR' than it is ok if you wrote it for your self only as you know how exactly it behaives, but if other programmes would have access to it it will be a disaster, belive me :) Or someone must look through commits to make sure it was used correctly. As it is not copy-protected I will repeat it has a class design bug. "You can interpret it so, but in my opinion you're just wrong" - I do not get why I am wrong if class instnace has very good probability to be ovewritten/copied resulting in memory leak and crash on N-th deallocation attempt.

Yes, you are correct that std::string fmtstrc(..) latest example was leaking dynamic memory and I actually forgot to fix it after a post, I corrected that post as I do not want to copy-paste it again here, do not blaim me for this :). It was a good example btw how malloca/freea could be misused by lack of attention of programmer, damn me! :)

ace,
you are inpolitedly trying to say that I correct my posts just to cheat you

No, I claim that you continuously attempt to cheat anybody who tries to read this thread by modifying old posts instead of writing the new content in the new posts. I just can't do more.

copy protection of classes is not that cosmic programming technique that only you are aware of

It's not, still you should be a man and admit that it didn't exist in your class and that you added that to yours only after you saw it in mine. I still don't remember seeing these lines in your class. I use C around 25 years, C++ around twenty and I see potential problems in the code really fast.

I do not get why I am wrong if class instnace has very good probability to be ovewritten/copied

Of course you don't as you don't understand basic principles – not every class must have all possible whistles and bells. In fact, the most classes shouldn't. It's only your problem that you believe that that what you wrote should be always used, even instead that every char buff[ M ]. In my humble opinion, your class shouldn't be used at all. That's how the potential programmer is protected the most.

I corrected that post as I do not want to copy-paste it again here, do not blaim me for this

So you keep doing that. That's exactly what finally convinces me that I shouldn't waste any more of my time on you.

To sum up: You made a class which was unnecessary complex. My comment pointed that. I initially didn't even want more than to say that. Later I even demonstrated exactly how much of what you did is wrong and unnecessary, I didn't even have to do that much, but I didn't expect that you will continue to misbehave. During the discussion you tried to fix more errors of yours in a way to make it appear that they didn't exist. During the discussion you increased the complexity of your class even more believing that it increases its value, bit it's still not worth. You still modify your old posts giving no chance to potential correspondent to refer to anything you wrote. Therefore you don't deserve to be treated as somebody with whom respectful discussion is possible. I think I served my "duty" (http://xkcd.com/386/) enough. I'd prefer to leave it to the others, if there are any survivors left, which I doubt.

Dmitry Kostjuchenko,

Ace, no problem, I also tired of this useless and pointless dscussion were you only trying to blaim me for anything while not introducing any real arguments which did make sense to me, let's stop these debates.

"It's not, still you should be a man and admit that it didn't exist in your class and that you added that to yours only after you saw it in mine" - sorry you are wrong, and I repeat, it is very pitty that these posts do not have SVN-like history, although I do not need to prove anything to you.

Some excessive complexity was added to introduce a debugging capability that could be useful for real life while also was an argument for your words of why not just using 'char x[256]'. I managed to show how besides just providing memory to user, such class can do useful debugging stuff just like 'malloca' in Debug compile under MSVC. COMPOSITE_ALLOC_IMLICIT_CAST define functionality was added after your words that (void *) operator looks ugly thus universal template cast operator was introduced for those who would find it same ugly. It was done for all other people not just for you :) I did not think that we were trying to fight for the goal who is smarter, I personally was trying to make class as flexible and useful as possible in terms of C/C++ coding practise. So we were pursueing different goals I guess.

Thank you for your time for this discussion, in some places I found it useful and that helped to improve 'composite_allocator'.

Nihlatak,

I'm sorry you had to go through this Dmitry.

Recently I got interested in alloca/malloca class implementations. I'll look into your implementation to gain some knowledge.

As for ace, he got nothing to look at all.

guziy,

Hi,

I am trying to use a c lib with ctypes and getting the following error

Error: in routine alloca() there is a

stack overflow: thread 0, max 137438739794KB, used 76KB, request 920B

could you, please, explain it ?

thanks

--

Sasha

Your name:


Comment:


Please ignore this field: