Obstack Introduction
Obstack initialization
Apply for an object in Obstack
Releasing objects
Apply Growing Object
Get Obstack Status
Data alignment
Here is an introduction to Obstack from the wiki:
Obstack is the GNU Extension for memory management in the C standard library (in fact, the GNU C Library). Obstack===object stack. Yes, Obstack is a stack, the elements inside the stack are object objects (not object-oriented objects Oh, here the object of the single exponential element). This data is dynamic, that is, using dynamic memory. This memory management technology belongs to the region-based memories management.
What do you call region-based memory management? Area refers to the location where the data objects we apply for are stored. In this memory management mode, we put all the requested data objects together (of course, the address is not necessarily contiguous.) Being lumped together is a logical structure, such as a stack of obstack. The advantage is that you can release memory at once and centralize management. Now you have a general understanding of Obstack.
The following is a description of the GNU C Obstack:
Obstack is a pool of memory with a stack of data objects in the memory pool.
What do you call a memory pool? The memory pool is also called a fixed-size block memory request (fixed-size blocks allocation), which is also a memory management technique. This technique allows for dynamic application of memory. (Are you confused?) The front also said fixed, and now said the dynamic. In fact fixed is the total size, dynamic refers to the actual application of memory to use. If you've ever used virtual box, that's exactly what 60 of people who have just played Linux will install. When creating a virtual hard disk, there is a description of the dynamic assignment: the virtual disk only gradually occupies the physical hard disk space [until the allocated size], but does not automatically reduce the physical hard disk space when its internal space is not used]) This approach is somewhat similar to the new operation of malloc or C + +. But malloc and new operations can cause memory fragmentation (don't hit me, it's a wiki, it's none of my business). The more efficient way is to use the same size pool of memory. Pre-application, centralized management. The application is free to play in the memory pool, never ashore -_-| | |
Go back and talk about Obstack. You can create any number of independent obstack, and then apply for objects within these obstack. These objects follow the logical structure of the stack: the last requested object must be released first. The data in different obstack is independent of each other and has no relation whatsoever. In addition to the requirements for memory release order, Obstack is very common: a obstack can contain any number of objects of any size.
Obstack memory application in the implementation of the general is a macro, very efficient bar. If you don't want to use a macro (the reason: Easy debugging), you can take a look at one of my other articles. The end of this article describes how to avoid using predefined macros. The only loss of memory space is that memory padding may be required between different objects, so that each object starts at the appropriate boundary line, which is in fact a space for time.
The expression of Obstack is a struct: struct obstack. This structure has a very small fixed size, records the state of the obstack, and how to find the object in the Obstack. However, the obstack structure itself does not contain any objects, do not be paranoid to directly explore the contents of the struct obstack. It is not negotiable to use the prescribed function.
You can create obstack by declaring a variable of struct obstack type. or dynamically apply struct obstack *obstack = (struct Obstack *) malloc (sizeof (struct obstack)); You can also obstack inside using obstack (and then egg, GNU C Library document itself)
The function used by obstack needs to specify the Obstack that is used. The objects inside the Obstack are packaged into a large block of memory (called chunks). The struct Obstack structure pointer points to the chunks currently in use.
A new chunk is created whenever the object you are applying to cannot be plugged into the previous chunk. In what form are these chunk connected (linked lists?) Tree? ), not our concern. These are automatically managed by Obstack. Chunk is created automatically by Obstack, but is created in a way that you decide, usually directly or indirectly, using the malloc function.
Lenovo we talked about the memory pool: Chunk is a fixed-size pool. Obstack is just a pool administrator: He told the people who came to bathe that they had to obey the rules and that the last one had to go first.
Obstack initialization:
#include <obstack.h>int obstack_init (struct obstack *obstack-ptr)
Obstack_init is actually a macro implementation. Obstack_init will automatically call the Obstack_chunk_alloc function to request chunk, note that this is a macro, you need to specify the function that the macro points to. If the memory request fails, the function that Obstack_alloc_failed_handler points to is called, and yes, it is still a macro. If the objects inside the chunk are freed, the Obstack_chunk_free-pointed function is used to return the space occupied by the chunk. The current version of Obstack_init always returns only 1 (the previous version will return 0 at the time of the failure)
Instance:
#include <obstack.h> #include <stdlib.h> #define obstack_chunk_alloc malloc #define obstack_chunk_free free// static application Obstack static struct Obstack myobstack;obstack_init ( &myobstack); // dynamic request Obstack struct obstack *myobstack_ptr = (struct obstack*) malloc (sizeof (struct Obstack)) Obstack_init (myobstack_ptr)
The size of the Obstack chunk is 4096 by default. If you want to customize the size of the chunk, you need to use a macro obstack_chunk_size
int obstack_chunk_size (struct obstack* obstack-ptr)
Note that this is actually an lvalue (a problematic lvalue reference in C + +, rvalue reference 囧rz). Obstack-ptr as shown in the previous Myobstack, indicates which Obstack. If you increase the size of the chunk properly, it is beneficial to improve efficiency. It doesn't do any good to reduce ...
if new-chunk-size) new-chunk-size
Apply for the object in Obstack:
The most straightforward way to use the Aobstack_alloc function
void * Obstack_alloc (structint size)
The
is called the same way as malloc, and the space for the new request is not initialized. If chunk is filled with object, Obstack_alloc will automatically call Obstack_chunk_alloc.
struct Obstack String_obstack; /* .... Initialize content .... */ Char * copystring (char *string) { = strlen (string1 ; char *s = (char*) obstack_alloc (&String_obstack, Len); string , Len); return s;}
If you want to initialize at the time of application, you need to use Obstack_copy or obstack_copy0
void * obstack_copy (structvoidint size)// The new request for the object memory size is also sizedvoid *obstack_copy0 (structvoid ) using the copy size data initialization from address int size) // add a null character to the obstack_copy but at the end, which is handy when copying a null-terminated string.
Release the object inside the Obstack:
Also very simple, we use the function Obstack_free
void obstack_free (structvoid *object)
If object is a null pointer, all objects are freed, leaving an uninitialized obstack, and the Obstack library automatically releases chunk. If you specify an object address, all objects after this object are freed. It is worth noting that if you want to release all objects but also keep obstack valid, you can specify the address of the first object
Obstack_free (Obstack_ptr, first_object_allocated_ptr);
Objects that can grow memory space:
Since the memory space of the Obstack chunk is continuous, the object space in it can be built up to the end in one step. This technique is called growing object. Although Obstack can use growing object, you cannot use this technique for objects that have already been applied (the reason is that if there are objects behind this object, it can cause a conflict)
voidObstack_blank (structObstack *obstack-ptr,intsize)//add a growing object that is initializedvoidObstack_grow (structObstack *obstack-ptr,void*data,intsize)//add an initialized space similar to the obstack_copyvoidObstack_grow0 (structObstack *obstack-ptr,void*data,intsize)//Obstack_grow similar to obstack_copy, that obstack_grow0 you say similar to who? voidObstack_lgrow (structObstack *obstack-ptr, Charc)//add one character at a time (bytes)voidObstack_ptr_grow (structObstack *obstack-ptr,void*data)//add one pointer at a time ... Size is (sizeof (void *)voidObstack_int_grow (structObstack *obstack-ptr,intdata)//add an int data at a time, with a size of sizeof (int)
The most important function in growing object is Obstack_finish, because the final address of the growing object is returned only after the function is called.
void *obstack_finish (struct obstrack *obstrack-ptr)
If you want to get growing object current size, you can use Obstack_object_size
int obstack_object_size (struct obstack *obstrack-ptr)// can only be used in Obstack_ Before finish, it will only return 0
If you want to cancel an object that is growing, you must end it before releasing it. Examples are as follows:
Obstack_free (Obstack_ptr, Obstack_finish (obstack_ptr))
The above function checks if there is enough space to add data. If you only add a tiny amount of space, checking this step is obviously superfluous. We can omit this step for faster growing. Here about growing object extra in introducing a function:
int obstack_room (struct obstack *obstack-ptr)// Returns the number of bytes that can be safely added
The rest of the quick Add function only needs to add the suffix _fast in the previous growing object function (if you're not sure you can see the GNU C Introduction to this section)
Status of Obstack:
The following function is used to get the state of Obstack:
void * obstack_base (struct Obstack *obstack-ptr) // Returns the assumed starting address of the object that is growing. Why is the assumption, because if you grow too large, the current chunk space is not enough, Obstack will create a new chunk, so that the address is changed. void *obstack_next_free (struct Obstack *obstack-ptr) Returns the address of the first byte not occupied by the current chunk int obstack_object_size (struct obstack *obstack-// Returns the size of the current growing object. Equivalent to: // obstack_next_free (Obstack-ptr) -obstack_base (obstack-ptr)
Data alignment issues in the Obstack
int obstack_alignment_mask (struct obstack *obstack-ptr)
When the macro expands, it is a left-hand value. If the function is implemented, the mask is returned. You should also be a mask to copy him. The value of the mask should be 2 n minus one, which means that the address must be a multiple of n times of 2. If you change the mask, it will only take effect the next time you apply for an object (special case is growing object: Immediate effect, you can see the effect after calling Obstack_finish)
This address http://www.cnblogs.com/san-fu-su/p/5739780.html
Linux C Obstack