Use of alloca function

Hello ,

i have read the manual page of alloca ,
it is documented there that "alloca works similar to the malloc but it allocates memory from stack and frees automatically".

i can't get how can i use that in a program .
if i'm not wrong can i use that like :

#include<stdio.h>
#include<alloca.h>
int main()
{
        void *p;
        p=alloca(20);
        if(p==NULL)
        {
                printf("alloca failed");
                exit(1);
        }
 
        strcpy(p,"Hello");
        printf("%s\n",p);
        printf("%u\n",p);
 
        return 0;
}
 

and what is the advantage of such a function.

even if i use array it also allocates memory from the stack and memory will be freed automatically.

what is the more advantage its having than array.

Have a read of this:

Advantages of Alloca - The GNU C Library

Regards

One advantage of alloca() that page doesn't directly address is that alloca() allocates memory that's already under the control of the thread that's making the call, so in multi-threaded applications alloca() can be many orders of magnitude faster than malloc()-based calls.

IMO the link on that page to alloca() disadvantages doesn't stress the major disadvantage of alloca() strongly enough - running out of memory. With malloc()-based allocation, you've got to get pretty extreme before you'll run out of memory. But with alloca(), all you have to work with is the stack of the current thread, which may be quite small, and unless you've directly addressed thread stack size is probably only a few MB at most.

In other words, in order to use alloca() safely you have to really, really know how much memory your entire process is using and where all that memory is coming from.

But if you take care and know what you're doing, you can make multi-threaded apps tremendously faster using alloca().

Use of alloca is discouraged because it is system dependent...also the memory returned cant be passed to other functions since it is freed as soon as the function that calls alloca exits. With alloca portability is the biggest concern if developing apps for different platforms.

How system dependent? Linux has it, Windows has it, IRIX has it, Solaris has it, BSD has it, OSX has it, HPUX seems to have it... The only platform I can think of offhand that I can't verify is AIX, and that's a "maybe", not a "no". It seems too useful, even internally, for vendors to not implement... I will admit that some embedded platforms implement it badly(a severe error on systems with no malloc!), allowing alloca'd memory to be overwritten by further function calls, but I'm not aware of an embedded platform with threading. I suspect the kind of stack management needed for threading also lets alloca exist.

You can certainly pass it to other functions if you keep in mind its scope, the exact same way you can pass references to stack variables if you keep in mind their scope. For a thread, it will be valid as long as the thread exists.

Please note any platforms you know of that don't have alloca.

AIX has it too. I work primarily on AIX and HP-UX platforms and their man pages explicitly state that alloca should not be used because it's sytem dependent. Why they dont say that...perhaps because different MPUs manage stacks differently. What if one mpu had its stack growing towards high memory instead of low memory...that itself would be a portability problem.

It's more so of an issue on embedded platforms because of the limited resources...why allocate memory with alloca in each function frame when you can allocate it once with malloc and keep reusing it.

It can certainly be passed to a nested function but can't be returned from one function to another the same way that a malloc'd pointer can be.

I don't know of any platforms that don't support alloca apart from embedded OSes however as the manpages say it is system dependent. Personally I have never used alloca because it is really of no use when it cant be returned. Curious if you can come up with a scenario where it's use would be more befitting than malloc.

FWIW - solaris alloca man page:

Maybe it has to do with implementing stack frames in different architectures from a single vendor? This is from an Ultrasparc IIIi multi-cpu box.

Linux:

I added the red.

Any time you want a local buffer without predefining its size, for one thing. achenle also had a good point about it being threadsafe hence much faster than trying to synchronize malloc for multithreaded things.

It's interesting how each platform discourages the use of alloca because of how it might behave on some other unmentionable platform without confessing to being guilty themselves. This could stand some testing, I think. alloca's almost as old as UNIX itself, circa AT&T V32 1979, making me wonder how historical this complaint is and how relevant it actually remains.

---------- Post updated at 04:24 PM ---------- Previous update was at 03:57 PM ----------

I wonder if this fails on any of your machines. I'm trying to smash stack memory in the manner described by passing and assigning to large stack variables as well as deep recursion.

#include <stdio.h>
#include <string.h>
#include <alloca.h>

struct hulk {   char buf[1024]; };

struct hulk smash(struct hulk h, int n)
{
        memset(&h, 0xff, sizeof(h));
        if(n > 0) h=smash(h, n-1);
        return(h);
}

int main(void)
{
        int n=0;
        struct hulk h;
        char *mem=alloca(sizeof(h));

        memset(mem, 0x7f, sizeof(h));
        memset(&h, 0x00, sizeof(h));
        h=smash(h, 5);

        for(n=0; n<sizeof(h); n++)
        {
                if(mem[n] != 0x7f)
                {
                        fprintf(stderr, "hulk smashed\n");
                        return(1);
                }
        }

        return(0);
}

So far OSX on PPC, and Linux on x86-32, x86-64, and embedded-linux MIPS(with ulibc) do not accidentally overwrite memory returned by alloca.

Thank You all for your replies.

alloca() is not part of any standard such as ISO C or POSIX for a very good reason. It is not fully portable across computing architectures and programming models. For example, how do you implement it on architectures which do not have a stack?

Since alloca() is not standardized you cannot rely on alloca() being threadsafe across implementations. It may or may not be.

What stack-free architectures? I can't find any except the PIC16, an embedded processor line with more I/O ports than RAM. And even then they were forced to emulate a stack to write a C compiler for it. I would have expected PPC or MIPS to be the ones to fail on this, being more RISC-like architectures that play funny games with the stack, but they work fine.

It's a very low-level call that works by modifying the stack frame -- a thread-local property. It would take an extremely strange implementation of it to not be threadsafe.

It is worth testing, though. I'll see what I can come up with.

A major problem with using alloca() is that it does not fail gracefully when it fails. Usually a SIGSEGV or SIGBUS occurs which is difficult to debug because the SIGSEGV or SIGBUS may not necessarily occur anywhere close to the alloca() call.

Such a crash may be reproducible in one specific environment but not in another. This is usually the result of different stacksizes. An application's default stacksize depends on the user environment and may have been modified via ulimit or some other mechanism. Furthermore, in a threaded application a thread stacksize may differ from the process stacksize and from another thread's stacksize.

This is just standard memory behavior. C's inability to warn you of impending stack faults doesn't stop people from using recursion and local variables, fortunately. If alloca is actually broken on some platform, though, that would be very good to know...

I get that but my question was more about how are you going to use a dynamically allocated stack buffer.

It's just as easy to do with malloc.

I would be leary of using a C lib function that is non-portable and strongly discouraged by the vendors who make it as it goes against the very purpose for which C was created i.e. portability. Otherwise we would all be coding in assembly which would be very cumbersome given the number of different mpus in the market today.

I have a hard copy of the UNIX Programmer's Manual (7th ed. Vol. 1 Jan. 1979) and alloca is nowhere in it.

int main(void)
{
        void *buffer=alloca(512);
        while(fread(stdin, 512, buffer) != NULL)
        { /* do stuff */ }
}

I already get there are ways you can't use it. That doesn't mean its useless. Nobody's forcing you to use it either.

Many implementations of malloc aren't threadsafe. But we're beginning to repeat ourselves here.

It's a stretch to call something that exists on any UNIX you can name, and beyond into the non-UNIX world, nonportable. But don't forget I'm trying to prove you right here. You're assuming it's problematic, I'm hunting for better reasons instead of assuming you're wrong.

In that respect I've found two items of interest; a makefile that suggests some historical System V's didn't have it, and an SCO compiler bug that happens under extremely specific circumstances. The latter is very interesting, I'll have to modify my tests to include it.

I never said it was in the standard or documentation -- I'd be shocked if it was. I didn't just make it up, though -- some sources think v32 has it.

Yes 32V had it. It was implemented as an assember routine in libc (/usr/src/libc/sys/alloca.s)

# like alloc, but automatic
# automatic free in return

.globl	_alloca
_alloca:
	.word	0x0000
	subl2	4(ap),sp            # crude allocation
	movl	16(fp),r1	                 # pc
	movq	8(fp),ap	         # new (old) ap and fp
	bicl2	$3,sp		         # 4-byte align
	addl2	$7*4,sp            # reuse space of mscp
	movl	sp,r0		         # return value
	jmp 	(r1)                           # funny return

Why use alloca()? Oh, how about a few orders of magnitude faster performance under multithreaded heap contention?

This

malloc() took 103497088262 ns
alloca() took 135368983 ns

came from this code:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <alloca.h>

#define BUFSIZE 8192
#define NUM_THR 8

static volatile int flag = 0;

typedef void ( *func_ptr )( void );

void test_malloc( void )
{
    void *ptr;
    ptr = malloc( BUFSIZE );
    free( ptr );
    return;
}

void test_alloca( void )
{
    void *ptr;
    ptr = alloca( BUFSIZE );
    return;
}

void *run( void *arg )
{
    func_ptr f;
    int ii;

    if ( flag )
        f = test_malloc;
    else
        f = test_alloca;
    for ( ii = 0; ii < ( 10 * 1024 * 1024 ); ii++ )
        f();
    return( NULL );
}

int main( int argc, char **argv )
{
    pthread_t tids[ NUM_THR ];
    hrtime_t start;
    hrtime_t end;
    void *status;
    int ii;

    flag = 1;
    start = gethrtime();
    for ( ii = 0; ii < NUM_THR; ii++ )
        pthread_create( &tids[ ii ], NULL, run, NULL );
    for ( ii = 0; ii < NUM_THR; ii++ )
        pthread_join( tids[ ii ], &status );
    end = gethrtime();
    printf( "malloc() took %lld ns\n", end - start );

    flag = 0;
    start = gethrtime();
    for ( ii = 0; ii < NUM_THR; ii++ )
        pthread_create( &tids[ ii ], NULL, run, NULL );
    for ( ii = 0; ii < NUM_THR; ii++ )
        pthread_join( tids[ ii ], &status );
    end = gethrtime();
    printf( "alloca() took %lld ns\n", end - start );
    return( 0 );
}

run under Solaris 10 running on an IBM e326m with 2 dual-core 2.4 GHz Opterons:

Considering how minimal alloca really is, I'd be worried about the compiler optimizing it away completely in your example...

All I m trying to say is that the value from alloca cant be returned from the function that called it. I most likely wont be using it since I have to deal with multiple platforms.

Care to list some platforms where the malloc implementation isnt threadsafe...just curious btw.

Not concerned about the right or wrong aspect of it. I probably am totally wrong...but as we deal with multiple platforms I am leary of something that's billed non-portable and strongly discouraged i.e. "dont want to rush in like a fool where vendors fear to tread"

Not a big deal again I was just curious why my copy didnt have it but as fpmurphy clarified it was an assembly routine.

i just compiled the program but i am getting the following errors

alloca.c: In function `main':
alloca.c:46: `hrtime_t' undeclared (first use in this function)
alloca.c:46: (Each undeclared identifier is reported only once
alloca.c:46: for each function it appears in.)
alloca.c:46: parse error before "start"
alloca.c:52: `start' undeclared (first use in this function)
alloca.c:57: `end' undeclared (first use in this function)

i think we are missing some header file.