昨天晚上下载了一份GCC V1.42的代码,不知道是源代码本身有问题,还是下载的源代码有问题,看的第一个C文件就存在一些很

奇怪的情况。

  首先要说的是: alloca.c 文件的作用,alloca.c文件的函数实现动态堆空间的分配,即运行时堆栈空间分配。

【1】源代码

  1 /*
  2     alloca -- (mostly) portable public-domain implementation -- D A Gwyn
  3 
  4     last edit:    86/05/30    rms
  5        include config.h, since on VMS it renames some symbols.
  6        Use xmalloc instead of malloc.
  7 
  8     This implementation of the PWB library alloca() function,
  9     which is used to allocate space off the run-time stack so
 10     that it is automatically reclaimed upon procedure exit, 
 11     was inspired by discussions with J. Q. Johnson of Cornell.
 12 
 13     It should work under any C implementation that uses an
 14     actual procedure stack (as opposed to a linked list of
 15     frames).  There are some preprocessor constants that can
 16     be defined when compiling for your specific system, for
 17     improved efficiency; however, the defaults should be okay.
 18 
 19     The general concept of this implementation is to keep
 20     track of all alloca()-allocated blocks, and reclaim any
 21     that are found to be deeper in the stack than the current
 22     invocation.  This heuristic does not reclaim storage as
 23     soon as it becomes invalid, but it will do so eventually.
 24 
 25     As a special case, alloca(0) reclaims storage without
 26     allocating any.  It is a good idea to use alloca(0) in
 27     your main control loop, etc. to force garbage collection.
 28 */
 29 
 30 
 31 #ifndef lint
 32     static char    SCCSid[] = "@(#)alloca.c    1.1";    /* for the "what" utility */
 33 #endif
 34 
 35 #ifdef emacs
 36     #include "config.h"
 37     #ifdef static
 38 /* actually, only want this if static is defined as " "
 39    -- this is for usg, in which emacs must undefine static
 40    in order to make unexec workable
 41    */
 42         #ifndef STACK_DIRECTION
 43             you
 44             lose
 45             -- must know STACK_DIRECTION at compile-time
 46         #endif /* STACK_DIRECTION undefined */
 47     #endif static 
 48 #endif emacs
 49 
 50 
 51 //很显然这里是对 X3J11 规范的定义
 52 #ifdef X3J11
 53     typedef void    *pointer;        /* generic pointer type */
 54 #else
 55     typedef char    *pointer;        /* generic pointer type */
 56 #endif
 57 
 58 //为什么这个地方不定义为 (void*)
 59 #define    NULL    0            /* null pointer constant */
 60 
 61 extern void    free();
 62 extern pointer    xmalloc();
 63 
 64 /*
 65     Define STACK_DIRECTION if you know the direction of stack
 66     growth for your system; otherwise it will be automatically
 67     deduced at run-time.
 68 
 69     STACK_DIRECTION > 0 => grows toward higher addresses
 70     STACK_DIRECTION < 0 => grows toward lower addresses
 71     STACK_DIRECTION = 0 => direction of growth unknown
 72 */
 73 
 74 
 75 //查看是否定义了栈增长方向宏定义
 76 #ifndef STACK_DIRECTION
 77     #define    STACK_DIRECTION    0        /* direction unknown */
 78 #endif
 79 
 80 //定义栈空间的增长方向宏 STACK_DIR
 81 #if  STACK_DIRECTION != 0
 82     #define    STACK_DIR    STACK_DIRECTION    /* known at compile-time */
 83 #else    /* STACK_DIRECTION == 0; need run-time code */
 84     static int    stack_dir;        /* 1 or -1 once known */
 85     #define    STACK_DIR    stack_dir
 86     //下面的函数用来判断栈的增长方向
 87     static void      
 88     find_stack_direction (/* void */)
 89     {
 90           static char    *addr = NULL;     /* address of first `dummy', once known */
 91           auto char    dummy;        /* to get stack address */
 92 
 93           if (addr == NULL)
 94             {                /* initial entry */
 95               addr = &dummy;
 96                find_stack_direction ();    /* recurse once */
 97          }
 98           else                /* second entry */
 99               if (&dummy > addr)
100                   stack_dir = 1;        /* stack grew upward */
101                else
102                  stack_dir = -1;        /* stack grew downward */
103     }
104 #endif    /* STACK_DIRECTION == 0 */
105 
106 
107 /*
108     An "alloca header" is used to:
109     (a) chain together all alloca()ed blocks;
110     (b) keep track of stack depth.
111 
112     It is very important that sizeof(header) agree with malloc()
113     alignment chunk size.  The following default should work okay.
114 */
115 
116 #ifndef    ALIGN_SIZE
117     #define    ALIGN_SIZE    sizeof(double)
118 #endif 
119 
120 typedef union hdr
121 {
122      char    align[ALIGN_SIZE];    /* to force sizeof(header) */
123      struct
124        {
125            union hdr *next;        /* for chaining headers */
126         char *deep;        /* for stack depth measure */
127      } h;
128 } header;
129 
130 /*
131     alloca( size ) returns a pointer to at least `size' bytes of
132     storage which will be automatically reclaimed upon exit from
133     the procedure that called alloca().  Originally, this space
134     was supposed to be taken from the current stack frame of the
135     caller, but that method cannot be made to work for some
136     implementations of C, for example under Gould's UTX/32.
137 */
138 
139 //全局变量用来存储 栈 指针
140 static header *last_alloca_header = NULL; /* -> last alloca header */
141 
142 //动态堆分配函数, 这个函数有点类似 malloc 函数
143 //但是这个函数具有垃圾回收机制
144 pointer
145 alloca (size)            /* returns pointer to storage */
146      unsigned    size;        /* # bytes to allocate */
147 {
148   auto char    probe;        /* probes stack depth: */
149   register char    *depth = &probe;
150 
151 #if  STACK_DIRECTION == 0
152       if (STACK_DIR == 0)        /* unknown growth direction */
153             find_stack_direction ();
154 #endif
155 
156 /* Reclaim garbage, defined as all alloca()ed storage that
157 was allocated from deeper in the stack than currently. */
158   {
159     register header    *hp;    /* traverses linked list */
160 
161       //可以发现这里for循环的语法非常特殊
162     for (hp = last_alloca_header; hp != NULL;)
163       if (STACK_DIR > 0 && hp->h.deep > depth || STACK_DIR < 0 && hp->h.deep < depth)
164       {
165          register header *np = hp->h.next;
166          free ((pointer) hp);    /* collect garbage */
167          hp = np;        /* -> next header */
168       }
169       else
170         break;            /* rest are not deeper */
171 
172     last_alloca_header = hp;    /* -> last valid storage */
173   }
174 
175   if (size == 0)
176     return NULL;        /* no allocation required */
177 
178   /* Allocate combined header + user data storage. */
179   {
180     register pointer new = xmalloc (sizeof (header) + size);
181     /* address of header */
182 
183     ((header *)new)->h.next = last_alloca_header;
184     ((header *)new)->h.deep = depth;
185 
186     last_alloca_header = (header *)new;
187 
188     /* User storage begins just after header. */
189     return (pointer)((char *)new + sizeof(header));
190    }
191 
192   }
View Code

相关文章: