⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memory.texi

📁 一个C源代码分析器
💻 TEXI
📖 第 1 页 / 共 5 页
字号:
@node Growing Objects@subsection Growing Objects@cindex growing objects (in obstacks)@cindex changing the size of a block (obstacks)Because storage in obstack chunks is used sequentially, it is possible tobuild up an object step by step, adding one or more bytes at a time to theend of the object.  With this technique, you do not need to know how muchdata you will put in the object until you come to the end of it.  We callthis the technique of @dfn{growing objects}.  The special functionsfor adding data to the growing object are described in this section.You don't need to do anything special when you start to grow an object.Using one of the functions to add data to the object automaticallystarts it.  However, it is necessary to say explicitly when the object isfinished.  This is done with the function @code{obstack_finish}.The actual address of the object thus built up is not known until theobject is finished.  Until then, it always remains possible that you willadd so much data that the object must be copied into a new chunk.While the obstack is in use for a growing object, you cannot use it forordinary allocation of another object.  If you try to do so, the spacealready added to the growing object will become part of the other object.@comment obstack.h@comment GNU@deftypefun void obstack_blank (struct obstack *@var{obstack-ptr}, int @var{size})The most basic function for adding to a growing object is@code{obstack_blank}, which adds space without initializing it.@end deftypefun@comment obstack.h@comment GNU@deftypefun void obstack_grow (struct obstack *@var{obstack-ptr}, void *@var{data}, int @var{size})To add a block of initialized space, use @code{obstack_grow}, which isthe growing-object analogue of @code{obstack_copy}.  It adds @var{size}bytes of data to the growing object, copying the contents from@var{data}.@end deftypefun@comment obstack.h@comment GNU@deftypefun void obstack_grow0 (struct obstack *@var{obstack-ptr}, void *@var{data}, int @var{size})This is the growing-object analogue of @code{obstack_copy0}.  It adds@var{size} bytes copied from @var{data}, followed by an additional nullcharacter.@end deftypefun@comment obstack.h@comment GNU@deftypefun void obstack_1grow (struct obstack *@var{obstack-ptr}, char @var{c})To add one character at a time, use the function @code{obstack_1grow}.It adds a single byte containing @var{c} to the growing object.@end deftypefun@comment obstack.h@comment GNU@deftypefun {void *} obstack_finish (struct obstack *@var{obstack-ptr})When you are finished growing the object, use the function@code{obstack_finish} to close it off and return its final address.Once you have finished the object, the obstack is available for ordinaryallocation or for growing another object.This function can return a null pointer under the same conditions as@code{obstack_alloc} (@pxref{Allocation in an Obstack}).@end deftypefunWhen you build an object by growing it, you will probably need to knowafterward how long it became.  You need not keep track of this as you growthe object, because you can find out the length from the obstack justbefore finishing the object with the function @code{obstack_object_size},declared as follows:@comment obstack.h@comment GNU@deftypefun int obstack_object_size (struct obstack *@var{obstack-ptr})This function returns the current size of the growing object, in bytes.Remember to call this function @emph{before} finishing the object.After it is finished, @code{obstack_object_size} will return zero.@end deftypefunIf you have started growing an object and wish to cancel it, you shouldfinish it and then free it, like this:@smallexampleobstack_free (obstack_ptr, obstack_finish (obstack_ptr));@end smallexample@noindentThis has no effect if no object was growing.@cindex shrinking objectsYou can use @code{obstack_blank} with a negative size argument to makethe current object smaller.  Just don't try to shrink it beyond zerolength---there's no telling what will happen if you do that.@node Extra Fast Growing@subsection Extra Fast Growing Objects@cindex efficiency and obstacksThe usual functions for growing objects incur overhead for checkingwhether there is room for the new growth in the current chunk.  If youare frequently constructing objects in small steps of growth, thisoverhead can be significant.You can reduce the overhead by using special ``fast growth''functions that grow the object without checking.  In order to have arobust program, you must do the checking yourself.  If you do this checkingin the simplest way each time you are about to add data to the object, youhave not saved anything, because that is what the ordinary growthfunctions do.  But if you can arrange to check less often, or checkmore efficiently, then you make the program faster.The function @code{obstack_room} returns the amount of room availablein the current chunk.  It is declared as follows:@comment obstack.h@comment GNU@deftypefun int obstack_room (struct obstack *@var{obstack-ptr})This returns the number of bytes that can be added safely to the currentgrowing object (or to an object about to be started) in obstack@var{obstack} using the fast growth functions.@end deftypefunWhile you know there is room, you can use these fast growth functionsfor adding data to a growing object:@comment obstack.h@comment GNU@deftypefun void obstack_1grow_fast (struct obstack *@var{obstack-ptr}, char @var{c})The function @code{obstack_1grow_fast} adds one byte containing thecharacter @var{c} to the growing object in obstack @var{obstack-ptr}.@end deftypefun@comment obstack.h@comment GNU@deftypefun void obstack_blank_fast (struct obstack *@var{obstack-ptr}, int @var{size})The function @code{obstack_blank_fast} adds @var{size} bytes to thegrowing object in obstack @var{obstack-ptr} without initializing them.@end deftypefunWhen you check for space using @code{obstack_room} and there is notenough room for what you want to add, the fast growth functionsare not safe.  In this case, simply use the corresponding ordinarygrowth function instead.  Very soon this will copy the object to anew chunk; then there will be lots of room available again. So, each time you use an ordinary growth function, check afterward forsufficient space using @code{obstack_room}.  Once the object is copiedto a new chunk, there will be plenty of space again, so the program willstart using the fast growth functions again.Here is an example:@smallexample@groupvoidadd_string (struct obstack *obstack, char *ptr, int len)@{  while (len > 0)    @{      if (obstack_room (obstack) > len)        @{          /* @r{We have enough room: add everything fast.}  */          while (len-- > 0)            obstack_1grow_fast (obstack, *ptr++);        @}      else        @{          /* @r{Not enough room. Add one character slowly,}             @r{which may copy to a new chunk and make room.}  */          obstack_1grow (obstack, *ptr++);          len--;        @}    @}@}@end group@end smallexample@node Status of an Obstack@subsection Status of an Obstack@cindex obstack status@cindex status of obstackHere are functions that provide information on the current status ofallocation in an obstack.  You can use them to learn about an object whilestill growing it.@comment obstack.h@comment GNU@deftypefun {void *} obstack_base (struct obstack *@var{obstack-ptr})This function returns the tentative address of the beginning of thecurrently growing object in @var{obstack-ptr}.  If you finish the objectimmediately, it will have that address.  If you make it larger first, itmay outgrow the current chunk---then its address will change!If no object is growing, this value says where the next object youallocate will start (once again assuming it fits in the currentchunk).@end deftypefun@comment obstack.h@comment GNU@deftypefun {void *} obstack_next_free (struct obstack *@var{obstack-ptr})This function returns the address of the first free byte in the currentchunk of obstack @var{obstack-ptr}.  This is the end of the currentlygrowing object.  If no object is growing, @code{obstack_next_free}returns the same value as @code{obstack_base}.@end deftypefun@comment obstack.h@comment GNU@deftypefun int obstack_object_size (struct obstack *@var{obstack-ptr})This function returns the size in bytes of the currently growing object.This is equivalent to@smallexampleobstack_next_free (@var{obstack-ptr}) - obstack_base (@var{obstack-ptr})@end smallexample@end deftypefun@node Obstacks Data Alignment@subsection Alignment of Data in Obstacks@cindex alignment (in obstacks)Each obstack has an @dfn{alignment boundary}; each object allocated inthe obstack automatically starts on an address that is a multiple of thespecified boundary.  By default, this boundary is 4 bytes.To access an obstack's alignment boundary, use the macro@code{obstack_alignment_mask}, whose function prototype looks likethis:@comment obstack.h@comment GNU@deftypefn Macro int obstack_alignment_mask (struct obstack *@var{obstack-ptr})The value is a bit mask; a bit that is 1 indicates that the correspondingbit in the address of an object should be 0.  The mask value should be oneless than a power of 2; the effect is that all object addresses aremultiples of that power of 2.  The default value of the mask is 3, so thataddresses are multiples of 4.  A mask value of 0 means an object can starton any multiple of 1 (that is, no alignment is required).The expansion of the macro @code{obstack_alignment_mask} is an lvalue,so you can alter the mask by assignment.  For example, this statement:@smallexampleobstack_alignment_mask (obstack_ptr) = 0;@end smallexample@noindenthas the effect of turning off alignment processing in the specified obstack.@end deftypefnNote that a change in alignment mask does not take effect until@emph{after} the next time an object is allocated or finished in theobstack.  If you are not growing an object, you can make the newalignment mask take effect immediately by calling @code{obstack_finish}.This will finish a zero-length object and then do proper alignment forthe next object.@node Obstack Chunks@subsection Obstack Chunks@cindex efficiency of chunks@cindex chunksObstacks work by allocating space for themselves in large chunks, andthen parceling out space in the chunks to satisfy your requests.  Chunksare normally 4096 bytes long unless you specify a different chunk size.The chunk size includes 8 bytes of overhead that are not actually usedfor storing objects.  Regardless of the specified size, longer chunkswill be allocated when necessary for long objects.The obstack library allocates chunks by calling the function@code{obstack_chunk_alloc}, which you must define.  When a chunk is nolonger needed because you have freed all the objects in it, the obstacklibrary frees the chunk by calling @code{obstack_chunk_free}, which youmust also define.These two must be defined (as macros) or declared (as functions) in eachsource file that uses @code{obstack_init} (@pxref{Creating Obstacks}).Most often they are defined as macros like this:@smallexample#define obstack_chunk_alloc xmalloc#define obstack_chunk_free free@end smallexampleNote that these are simple macros (no arguments).  Macro definitions witharguments will not work!  It is necessary that @code{obstack_chunk_alloc}or @code{obstack_chunk_free}, alone, expand into a function name if it isnot itself a function name.If you allocate chunks with @code{malloc}, the chunk size should be apower of 2.  The default chunk size, 4096, was chosen because it is longenough to satisfy many typical requests on the obstack yet short enoughnot to waste too much memory in the portion of the last chunk not yet used.@comment obstack.h@comment GNU@deftypefn Macro int obstack_chunk_size (struct obstack *@var{obstack-ptr})This returns the chunk size of the given obstack.@end deftypefnSince this macro expands to an lvalue, you can specify a new chunk size byassigning it a new value.  Doing so does not affect the chunks alreadyallocated, but will change the size of chunks allocated for that particularobstack in the future.  It is unlikely to be useful to make the chunk sizesmaller, but making it larger might improve efficiency if you areallocating many objects whose size is comparable to the chunk size.  Hereis how to do so cleanly:@smallexampleif (obstack_chunk_size (obstack_ptr) < @var{new-chunk-size})  obstack_chunk_size (obstack_ptr) = @var{new-chunk-size};@end smallexample@node Summary of Obstacks@subsection Summary of Obstack FunctionsHere is a summary of all the functions associated with obstacks.  Eachtakes the address of an obstack (@code{struct obstack *}) as its firstargument.@table @code@item void obstack_init (struct obstack *@var{obstack-ptr})Initialize use of an obstack.  @xref{Creating Obstacks}.@item void *obstack_alloc (struct obstack *@var{obstack-ptr}, int @var{size})Allocate an object of @var{size} uninitialized bytes.@xref{Allocation in an Obstack}.@item void *obstack_copy (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size})Allocate an object of @var{size} bytes, with contents copied from@var{address}.  @xref{Allocation in an Obstack}.@item void *obstack_copy0 (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size})Allocate an object of @var{size}+1 bytes, with @var{size} of them copiedfrom @var{address}, followed by a null character at the end.@xref{Allocation in an Obstack}.@item void obstack_free (struct obstack *@var{obstack-ptr}, void *@var{object})Free @var{object} (and everything allocated in the specified obstackmore recently than @var{object}).  @xref{Freeing Obstack Objects}.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -