malloc() und calloc() haben einen recht großen Overhead, was RAM und Flash-Verbrauch angeht. Immerhin muss eine Liste der allokierten Blöcke verwaltet werden, und das frisst RAM. Ausserdem führen aufeinander folgende malloc/free Zyklen zu einer Speicherfragmentierung, so daß evtl kein passender Block mehr verfügbar ist.
Seltsamerweise kennt avr-gcc kein alloca(), aber so geht's:Synopsis:Code:#include <stdlib.h> void foo (unsigned short nbytes) { unsigned short i; unsigned char *buf; buf = (unsigned char*) __builtin_alloca ((size_t) nbytes); for (i=0; i < nbytes; i++) buf[i] = 0; }
void* __builtin_alloca (size_t nbytes);
__builtin_alloca() ist keine libc-Funktion wie malloc() und calloc(), sondern ein Builtin von GCC.
Der Speicherplatz wird auf dem Stapel angelegt, indem einfach der Stackpointer entsprechend angepasst wird:Vom Overhead ist so was optimal, allerdings ist das Bereich nicht vorinitialisiert und muss auch nicht freigegeben werden, das geschieht am Ende des C-Blocks automatisch. Der Bereich ist daher nur innerhalb des Blocks gültig, der ihn beschafft hat. Mit return einen Zeiger auf den Bereich rausliefern ist also nicht.Code:.text .global foo .type foo, @function foo: /* prologue: frame size=0 */ push r28 push r29 in r28,__SP_L__ in r29,__SP_H__ /* prologue end (size=4) */ in r20,__SP_L__ ; tmp47 ; 41 *movhi/7 [length = 2] in r21,__SP_H__ ; tmp47 in r18,__SP_L__ ; ; 76 *movhi/7 [length = 2] in r19,__SP_H__ ; sub r18,r24 ; , nbytes ; 11 subhi3/1 [length = 2] sbc r19,r25 ; , nbytes in __tmp_reg__,__SREG__ ; 77 *movhi/6 [length = 5] cli out __SP_H__,r19 ; out __SREG__,__tmp_reg__ out __SP_L__,r18 ; subi r18,lo8(-(1)) ; buf, ; 12 *addhi3/4 [length = 2] sbci r19,hi8(-(1)) ; buf, sbiw r24,0 ; nbytes ; 52 tsthi/1 [length = 1] breq .L7 ; , ; 53 branch [length = 1] movw r30,r18 ; buf, buf ; 68 *movhi/1 [length = 1] .L5: st Z+,__zero_reg__ ; , ; 25 *movqi/3 [length = 1] sbiw r24,1 ; i, ; 70 *addhi3/3 [length = 1] brne .L5 ; , ; 72 branch [length = 1] .L7: in __tmp_reg__,__SREG__ ; 44 *movhi/6 [length = 5] cli out __SP_H__,r21 ; tmp47 out __SREG__,__tmp_reg__ out __SP_L__,r20 ; tmp47 /* epilogue: frame size=0 */ pop r29 pop r28 ret
...und ein Laufzeit-Check ob der Platz noch ausreicht scheints auch nicht zu geben, evtl kann man das selber erledigen.
Mit gcc-Option -fstack-check wird anderer Code generiert, vielleicht tut's die ja schon...?
::Edit::
...und ANSI-C ist alloca() auch nicht, sondern GNU-C.
avr-gcc -ansi ...
wird das also anmeckern, sollte zumindest.







Zitieren
Lesezeichen