昨天晚上下载了一份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 }