.fp 5 CW .de MW \f3\\$1\fP .. .TH VMALLOC 3 "1 May 1998" .SH NAME vmalloc \- virtual memory allocation .SH SYNOPSIS .MW "#include " .SS Regions .nf .MW "Vmalloc_t* vmopen(Vmdisc_t* disc, Vmethod_t* meth, int flags);" .MW "int vmclose(Vmalloc_t*);" .MW "int vmclear(Vmalloc_t*);" .MW "int vmcompact(Vmalloc_t* region);" .MW "int vmset(Vmalloc_t* region, int flags, int type);" .MW "Vmalloc_t* Vmheap;" .MW "Vmdisc_t* vmdisc(Vmalloc_t* region, Vmdisc_t* disc);" .MW "Vmalloc_t* vmmopen(char* file, int project, ssize_t size);" .MW "Void_t* vmmvalue(Vmalloc_t* vm, int key, Void_t* value, int op);" .MW "Void_t* vmmcleanup(Vmalloc_t* vm);" .MW "Void_t* vmmaddress(size_t size);" .fi .SS "Allocation functions" .nf .MW "Void_t* vmalloc(Vmalloc_t* region, size_t size);" .MW "Void_t* vmalign(Vmalloc_t* region, size_t size, size_t align);" .MW "Void_t* vmresize(Vmalloc_t* region, Void_t* addr, size_t size, int type);" .MW "int vmfree(Vmalloc_t* region, Void_t* addr);" .MW "Void_t* vmnewof(Vmalloc_t* region, Void_t* addr, type, size_t n, size_t x);" .MW "Void_t* vmoldof(Vmalloc_t* region, Void_t* addr, type, size_t n, size_t x);" .MW "Void_t* vmgetmem(Vmalloc_t* region, Void_t* addr, size_t size);" .fi .SS "Debugging" .nf .MW "int vmdebug(int);" .MW "int vmdbcheck(Vmalloc_t* vm);" .MW "int vmdbwatch(Void_t* addr);" .MW "static void vmdbwarn(Vmalloc_t*, char* mesg, int n);" .fi .SS "Profiling" .nf .MW "void vmprofile(Vmalloc_t* vm, int fd);" .fi .SS "Information and statistics" .nf .MW "int vmbusy(Vmalloc_t* region);" .MW "Vmalloc_t* vmregion(Void_t* addr);" .MW "Void_t* vmsegment(Vmalloc_t* region, Void_t* addr);" .MW "int vmwalk(Vmalloc_t* region, int(*walkf)(Vmalloc_t*, Void_t*, size_t, Vmdisc_t*);" .MW "long vmaddr(Vmalloc_t* region, Void_t* addr);" .MW "long vmsize(Vmalloc_t* region, Void_t* addr);" .MW "int vmstat(Vmalloc_t* vm, Vmstat_t* statb);" .MW "int vmtrace(int fd);" .MW "int vmtrbusy(Vmalloc_t* vm);" .MW "Void_t* vmdata(Vmalloc_t* vm);" .fi .SS "Malloc-compatible functions" .nf .MW "Void_t* malloc(size_t size);" .MW "Void_t* realloc(Void_t* addr, size_t size);" .MW "Void_t* calloc(size_t n_obj, size_t s_obj);" .MW "int cfree(Void_t* addr);" .MW "void free(Void_t* addr);" .MW "Void_t* memalign(size_t align, size_t size);" .MW "Void_t* valloc(size_t size);" .MW "int setregmax(int regmax);" .fi .SH DEPRECATION NOTICE In the 2021 ksh 93u+m distribution, \fIvmalloc\fP(3) was deprecated for being unstable and wasteful in comparison to \fImalloc\fP(3) implementations that come with modern operating systems. By default, the interfaces described here map to the OS's standard \fImalloc\fP(3) implementation. \fIvmalloc\fP can be enabled at compile time by passing \fB-D_AST_vmalloc\fP in \fBCCFLAGS\fP. .SH DESCRIPTION These functions for dynamic storage allocation work in \fIregions\fP of memory. Each region has an \fIallocation method\fP for parceling out blocks of storage and a \fImemory discipline\fP for obtaining raw space. Automatic locking prevents interference by reentrant access to a region. .PP Pointers to space have type \f3Void_t*\fP where \f3Void_t\fP is \f3#define\fPd as \f3void\fP if possible, otherwise \f3char\fP. Space is counted in type \f3size_t\fP. .ne 4 .SS Regions Regions have type \f3Vmalloc_t\fP. Two predefined regions are pointed to by: .TP .MW Vmheap A general-purpose region, with best-fit allocation, and system memory discipline \f3Vmdcsystem\fP. .PP These functions manipulate regions: .PP .I vmopen creates a region with memory discipline \fIdisc\fP, allocation method \fImeth\fP, and a setting for control \fIflags\fP. It returns a pointer to the region on success and \f3NULL\fP on failure. The flags, represented by bit values or-ed together, are: .TP .MW VM_SHARE This region may be accessed concurrently by multiple threads or processes. .TP .MW VM_TRACE Place tracing messages for each allocation event on the tracing file established by \fIvmtrace\fP. .TP \f3VM_DBCHECK\fP, \f3VM_DBABORT\fP .br See \fBDebugging\fP below. .PP .I vmclose closes a \fIregion\fP and releases all associated memory according to the region's discipline. The first segment obtained from the discipline's \f3memoryf\fP function (see `Disciplines' below) will be the last released. \fIvmclose\fP returns \-1 on failure and a non-negative value otherwise. .PP .I vmclear frees all allocated blocks in \fIregion\fP regardless of methods. It returns \-1 on failure and a non-negative value otherwise. .PP .I vmcompact releases as much of a \fIregion\fP's free space to its discipline's \f3memoryf\fP function as possible. It returns a nonnegative value on success and \-1 on failure. .PP .I vmset adjusts and queries a \fIregion\fP's \fIflags\fP. The indicated flags are turned on if \fItype\fP is nonzero, off if zero. \fIvmset\fP returns the previous value of all flags. Thus, \f3vmset(region,0,0)\fP queries the flags without changing them. In addition to the settable flags, one of \f3VM_MTBEST\fP, \f3VM_MTDEBUG\fP, \f3VM_MTPROFILE\fP, \f3VM_MTPOOL\fP, or \f3VM_MTLAST\fP is returned to indicate the method used in creating the \fIregion\fP. .PP .I vmdisc changes the discipline of \fIregion\fP to the given new discipline \fIdisc\fP if \fIdisc\fP is not \f3NULL\fP and its \f3memoryf\fP function is the same as the current discipline. If the current discipline has an \f3exceptf\fP function, it will be called with event \f3VM_DISC\fP. This function always returns the current discipline. .PP .I vmmopen creates a region to allocate memory obtained via either \fImmap(2)\fP when \fIproject < 0\fP or \fIshmget(2)\fP when \fIproject >= 0\fP. The region is built from a single memory segment guaranteed to be at least as large as \fIsize\fP. When \fIproject >= 0\fP, \fIfile\fP and \fIproject\fP are used in a call to \fIftok(3)\fP to get a key suitable for getting a shared memory segment via \fIshmget(2)\fP. Otherwise, \fIfile\fP is the backing store for the mapped data. In this case, not only the region may be used concurrently by different processes, it is also persistent. That is, process could even exit, move the file to a different but similar machine then restart and open the same region to continue working. .PP Note that Vmalloc can protect concurrent accesses only on region entry and exit for memory allocation operations. This means that at the time when regions are being opened or closed, there will be no protection for the memory segments being attached into or detached from process memory space. This limitation has a special impact on \fIvmmopen()\fP as follows. .PP A shared memory segment opened via \fIvmmopen()\fP corresponds uniquely to a combination of the \fIfile\fP and \fIproject\fP parameters. Thus, if multiple \fIvmmopen()\fP calls are done in the same process using a same combination of \fIfile\fP and \fIproject\fP, the joined behavior of such regions will be unpredictable when opening and closing are done concurrently with other memory allocation operations. Beware that this effect can be subtle with library functions that may attempt to create their own memory allocation regions. .PP .I vmmvalue manages pairs of \fIkey\fP and \fIvalue\fP in a region opened via \fIvmopen()\fP. If \fIop\fP is \f3VM_MMGET\fP, the value associated with \f3key\fP is returned. If \fIop\fP is \f3VM_MMSET\fP, the value associated with \f3key\fP will be set to \fIvalue\fP. If \fIop\fP is \f3VM_MMADD\fP, the value associated with \f3key\fP will be treated as a signed long value to which \f3val\fP (also treated as a signed long value) will be added. The call always returns the updated data value associated with \fIkey\fP. .PP .I vmmcleanup sets region up to remove backing store or \fIshmid\fP on closing. .PP .I vmmaddress computes an address suitable for attaching a shared memory segment or memory mapping a segment of file data of the given \fIsize\fP. The address is chosen with hope to minimize collision with other activities related to memory such as growth of stack space or space used for dynamically linked libraries, etc. .SS "Allocation functions" .I vmalloc returns a pointer to a block of the requested \fIsize\fP in a \fIregion\fP, aligned to the \fIstrictest alignment\fP that is suitable for the needs of any basic data type. It returns \f3NULL\fP on failure. .PP .I vmalign works like \fIvmalloc\fP, but returns a block aligned to a common multiple of \fIalign\fP and the \fIstrictest alignment\fP. .PP .I vmresize attempts to change the length of the block pointed to by \fIaddr\fP to the specified \fIsize\fP. If that is impossible and \fItype\fP has at least one of \f3VM_RSMOVE\fP and \f3VM_RSCOPY\fP, a new block is allocated and the old block is freed. The bit \f3VM_RSCOPY\fP also causes the new block to be initialized with as much of the old contents as will fit. When a resized block gets larger, the new space will be cleared if \fItype\fP has the bit \f3VM_RSZERO\fP. \fIvmresize\fP returns a pointer to the final block, or \f3NULL\fP on failure. If \fIaddr\fP is \f3NULL\fP, \fIvmresize\fP behaves like \fIvmalloc\fP; otherwise, if \fIsize\fP is 0, it behaves like \fIvmfree\fP. .PP .I vmfree makes the currently allocated block pointed to by \fIaddr\fP available for future allocations in its \fIregion\fP. If \fIaddr\fP is \f3NULL\fP, \fIvmfree\fP does nothing. It returns \-1 on error, and nonnegative otherwise. .PP .I vmnewof is a macro function that attempts to change the length of the block pointed to by \fIaddr\fP to the size \f3n*sizeof(type)+x\fP. If the block is moved, new space will be initialized with as much of the old content as will fit. Additional space will be set to zero. .PP .I vmoldof is similar to \fIvmnewof\fP but it neither copies data nor clears space. .PP .I vmgetmem provides a handy function to create/close regions and allocate/free memory based on chunks of memory obtained from the heap region \fIVmheap\fP. .TP .MW "vmgetmem(0,0,0)" This call opens a new region. .TP .MW "vmgetmem(region, 0, 0)" This call closes the given \f3region\fP. .TP .MW "vmgetmem(region,0,n)" This call allocates a block of length \f3n\fP and clears it to zeros. .TP .MW "vmgetmem(region,p,0)" This call frees the block \f3p\fP. .TP .MW "vmgetmem(region,p,n)" This call resizes the block \f3p\fP to length \f3n\fP and clears the new memory to zeros if the block grows. The block may be moved as deemed necessary by the allocator. .PP .SS "Memory disciplines" Memory disciplines have type \f3Vmdisc_t\fP, a structure with these members: .in +.5i .nf .MW "Void_t* (*memoryf)(Vmalloc_t *region, Void_t* obj," .ti +.5i .MW "size_t csz, size_t nsz, Vmdisc_t *disc);" .MW "int (*exceptf)(Vmalloc_t *region, int type, Void_t* obj, Vmdisc_t *disc);" .MW "int round;" .fi .in -.5i .TP .MW round If this value is positive, all size arguments to the \f3memoryf\fP function will be multiples of it. .TP .MW memoryf Points to a function to get or release segments of space for the \fIregion\fP. .TP .MW exceptf If this pointer is not \f3NULL\fP, the function it points to is called to announce events in a \fIregion\fP. .PP There are two standard disciplines, both with \f3round\fP being 0 and \f3exceptf\fP being \f3NULL\fP. .TP .MW Vmdcsystem A discipline whose \f3memoryf\fP function gets space from the operation system via different available methods which include \fImmap(2)\fP, \fIsbrk(2)\fP and functions from the WIN32 API. For historical reason, \fIVmdcsbrk\fP is also available and functions like \fIVmdcsystem\fP. .TP .MW Vmdcheap A discipline whose \f3memoryf\fP function gets space from the region \f3Vmheap\fP. A region with \f3Vmdcheap\fP discipline and \f3Vmlast\fP allocation is good for building throwaway data structures. .PP A \fImemoryf\fP function returns a pointer to a memory segment on success, and \f3NULL\fP on failure. When \fInsz >= 0\fP and \fIcsz > 0\fP, the function first attempts to change the current segment \fIaddr\fP to fit \fInsz\fP (for example, \fInsz == 0\fP means deleting the segment \fIaddr\fP). If this attempt is successful, it should return \fIaddr\fP. Otherwise, if \fInsz > csz\fP, the function may try to allocate a new segment of size \fInsz-csz\fP. If successful, it should return the address of the new segment. In all other cases, it should return NULL. .PP An \fIexceptf\fP function is called for events identified by \fItype\fP, which is coded thus: .TP .MW VM_OPEN This event is raised at the start of the process to open a new region. Argument \fIobj\fP will be a pointer to an object of type \f3Void_t*\fP initialized to NULL before the call. The return value of \fIexceptf\fP is significant as follows: On a negative return value, \fIvmopen\fP will terminate with failure. On a zero return value, \fIexceptf\fP may set \f3*((Void_t**)obj)\fP to some non-NULL value to tell \fIvmopen\fP to allocate the region handle itself via \fImemoryf\fP. Otherwise, the region handle will be allocated from the \f3Vmheap\fP region. On a positive return value, the new region is being reconstructed based on existing states of some previous region. In this case, \fIexceptf\fP should set \f3*(Void_t**)\fP\fIobj\fP to point to the field \f3Vmalloc_t.data\fP of the corresponding previous region (see \f3VM_CLOSE\fP below). If the handle of the previous region was allocated via \fImemoryf\fP as discussed above in the case of the zero return value, then it will be exactly restored. Otherwise, a new handle will be allocated from \f3Vmheap\fP. The ability to create regions sharing the same states allows for managing shared and/or persistent memory. .TP .MW VM_ENDOPEN This event is raised at the end of the process to open a new region. The return value of \fIexceptf\fP will be ignored. .TP .MW VM_CLOSE This event is raised at the start of the process to close a region, The return value of \fIexceptf\fP is significant as follows: On a negative return value, \fIvmclose\fP immediately returns with failure. On a zero return value, \fIvmclose\fP proceeds normally by calling \f3memoryf\fP to free all allocated memory segments and also freeing the region itself. On a positive return value, \fIvmclose\fP will only free the region without deallocating the associated memory segments. That is, the field \fIVmalloc_t.data\fP of the region handle remains intact. This is useful for managing shared and/or persistent memory (see \f3VM_OPEN\fP above). .TP .MW VM_ENDCLOSE This event is raised at the end of the process to close a region. The return value of \fIexceptf\fP will be ignored. .TP .MW VM_NOMEM An attempt to extend the region by the amount \f3(size_t)\fP\fIobj\fP failed. The region is unlocked, so the \fIexceptf\fP function may free blocks. If the function returns a positive value the memory request will be repeated. .TP .MW VM_DISC The discipline structure is being changed. .SS "Allocation methods" Methods are of type \f3Vmethod_t*\fP. .TP .MW Vmbest An approximately best-fit allocation strategy. .TP .MW Vmlast A strategy for building structures that are only deleted in whole. Only the latest allocated block can be freed. This means that as soon as a block \f3a\fP is allocated, \fIvmfree\fP calls on blocks other than \c5a\fP are ignored. .TP .MW Vmpool A strategy for blocks of one size, set by the first \fIvmalloc\fP call after \fIvmopen\fP or \fIvmclear\fP. .TP .MW Vmdebug An allocation strategy with extra-stringent checking and locking. It is useful for finding misuses of dynamically allocated memory, such as writing beyond the boundary of a block, or freeing a block twice. .ne 3 .TP .MW Vmprofile An allocation method that records and prints summaries of memory usage. .SS Debugging The method \f3Vmdebug\fP is used to debug common memory violation problems. When a problem is found, a warning message is written to file descriptor 2 (standard error). In addition, if flag \f3VM_DBABORT\fP is on, the program is terminated by calling \fIabort\fP(2). Each message is a line of self-explanatory fields separated by colons. The optional flag \f3-DVMFL\fP, if used during compilation, enables recording of file names and line numbers. The following functions work with method \f3Vmdebug\fP. .PP .I vmdebug resets the file descriptor to write out warnings to the given argument. By default, this file descriptor is 2, the standard error. \fIvmdebug\fP returns the previous file descriptor. .PP .I vmdbcheck checks a region using \f3Vmdebug\fP or \f3Vmbest\fP for integrity. If \f3Vmdebug\fP, this also checks for block overwriting errors. On errors, \fIvmdbwarn\fP is called. If flag \f3VM_DBCHECK\fP is on, \fIvmdbcheck\fP is called at each invocation of \fIvmalloc\fP, \fIvmfree\fP, or \fIvmresize\fP. .PP .I vmdbwatch causes address \fIaddr\fP to be watched, and reported whenever met in \fIvmalloc\fP, \fIvmresize\fP or \fIvmfree\fP. The watch list has finite size and if it becomes full, watches will be removed in a first-in-first-out fashion. If \fIaddr\fP is \f3NULL\fP, all current watches are canceled. \fIvmdbwatch\fP returns the watch bumped out due to an insertion into a full list or \f3NULL\fP otherwise. .PP .I vmdbwarn is an internal function that processes warning messages for discovered errors. It can't be called from outside the \fIvmalloc\fP package, but is a good place to plant debugger traps because control goes there at every trouble. .SS "Profiling" The method \f3Vmprofile\fP is used to profile memory usage. Profiling data are maintained in private memory of a process so \f3Vmprofile\fP should be avoided from regions manipulating persistent or shared memory. The optional flag \f3-DVMFL\fP, if used during compilation, enables recording of file names and line numbers. .PP .I vmprofile prints memory usage summary. The summary is restricted to region \fIvm\fP if \fIvm\fP is not \f3NULL\fP; otherwise, it is for all regions created with \f3Vmprofile\fP. Summary records are written to file descriptor \fIfd\fP as lines with colon-separated fields. Here are some of the fields: .TP .I n_alloc,n_free: Number of allocation and free calls respectively. Note that a resize operation is coded as a free and an allocation. .TP .I s_alloc,s_free: Total amounts allocated and freed. The difference between these numbers is the amount of space not yet freed. .TP .I max_busy, extent: These fields are only with the summary record for region. They show the maximum busy space at any time and the extent of the region. .SS "Information and statistics" .I vmbusy returns the busy status of a region. A region is busy if some allocation operation is accessing it. .PP .I vmregion returns the region to which the block pointed to by \fIaddr\fP belongs. This works only in regions that allocate with \f3Vmbest\fP, \f3Vmdebug\fP or \f3Vmprofile\fP. .PP .I vmsegment finds if some segment of memory in \fIregion\fP contains the address \fIaddr\fP. It returns the address of a found segment or \f3NULL\fP if none found. .PP .I vmwalk walks all segments in \fIregion\fP or if \fIregion\fP is \f3NULL\fP, all segments in all regions. At each segment, \fI(*walkf)(vm,addr,size,disc)\fP is called where \fIvm\fP is the region, \fIaddr\fP is the segment, \fIsize\fP is the size of the segment, and \fIdisc\fP is the region's discipline. If \fIwalkf\fP returns a negative value, the walk stops and returns the same value. On success, \fIvmwalk\fP returns 0; otherwise, it returns \-1. .PP .I vmaddr checks whether \fIaddr\fP points to an address within some allocated block of the given region. If not, it returns \-1. If so, it returns the offset from the beginning of the block. The function does not work for a \f3Vmlast\fP region except on the latest allocated block. .PP .I vmsize returns the size of the allocated block pointed to by \fIaddr\fP. It returns \-1 if \fIaddr\fP does not point to a valid block in the region. Sizes may be padded beyond that requested; in particular no block has size 0. The function does not work for a \f3Vmlast\fP region except on the latest allocated block. .PP .I vmstat gathers statistics on the given \fIregion\fP. If \f3region\fP is NULL, it computes statistics for the \fIMalloc\fP calls. This may include summing statistics from more than one regions constructed to avoid blocking due to parallel or asynchronous operations. If \fIstatb\fP is not NULL, \fIvmstat\fP computes and stores the statistics in \fIstatb\fP then returns 0. If \fIstatb\fP is NULL, no statistics will be computed and the returned value is either 1 if the region is busy, i.e., being accessed by some allocation call or 0 otherwise. A \f3Vmstat_t\fP structure has at least these members: .in +.5i .nf .ta \w'\f3size_t \fP'u +\w'\f3extent \fP'u .MW "int n_busy; /* # of busy blocks */ .MW "int n_free; /* # of free blocks */ .MW "size_t s_busy; /* total busy space */ .MW "size_t s_free; /* total free space */ .MW "size_t m_busy; /* maximum busy block size */ .MW "size_t m_free; /* maximum free block size */ .MW "int n_seg; /* count of segments */ .MW "size_t extent; /* memory extent of region */ .MW "int n_region; /* total Malloc regions */ .MW "int n_open; /* non-blocked operations */ .MW "int n_lock; /* blocked operations */ .MW "int n_probe; /* region searches */ .fi .in -.5i .PP Bookkeeping overhead is counted in \f3extent\fP, but not in \f3s_busy\fP or \f3s_free\fP. .PP .I vmtrace establishes file descriptor \fIfd\fP as the trace file and returns the previous value of the trace file descriptor. The trace descriptor is initially invalid. Output is sent to the trace file by successful allocation events when flag \f3VM_TRACE\fP is on. .PP Tools for analyzing traces are described in \fImtreplay\fP(1). The trace record for an allocation event is a line with colon-separated fields, four numbers and one string. .TP .I old Zero for a fresh allocation; the address argument for freeing and resizing. .TP .I new Zero for freeing; the address returned by allocation or resizing. .TP .I size The size argument for allocation or resizing; the size freed by freeing. Sizes may differ due to padding for alignment. .TP .I region The address of the affected region. .TP .I method A string that tells the region's method: \f3best\fP, \f3last\fP, \f3pool\fP, \f3profile\fP, or \f3debug\fP. .PP .I vmtrbusy outputs a trace of all currently busy blocks in region \f3vm\fP. This only works with the \f3Vmbest\fP, \f3Vmdebug\fP and \f3Vmprofile\fP methods. .PP .I vmdata returns the core data of the given region. The core data hold the data structures for allocated and free blocks. Depending on the region discipline, the core data of a region may be in shared or persistent memory even if the region pointer created with \fIvmopen\fP is always in private process memory. .SS "Malloc-compatible functions" This set of functions implement \fImalloc\fP(3). They allocate via the \fIVmregion\fP region which is initially set to be \fIVmheap\fP. Concurrent accesses are supported unless an application change \fIVmregion\fP to something other than \fIVmheap\fP. New regions may be created on the fly to avoid blocking. The maximum number of regions that can be created this way is set to 64 by default. An application could reduce this number by calling \fIsetregmax(regmax)\fP to set the maximum number of these extra regions to \fIregmax\fP. \fIsetregmax()\fP always returns the previous value. .PP These functions are instrumented for run-time debugging, profiling and tracing. For accurate reporting of files and line numbers, application code should include \f3vmalloc.h\fP and compile with \f3-DVMFL\fP. The \fBVMALLOC_OPTIONS\fP environment variable, checked once before the first memory allocation, controls the memory allocation method, debugging and tracing; its value is a comma or space separated list of \fB[no]\fP\fIname\fP\fB[=\fP\fIvalue\fP\fB]\fP options. The options are: .TP .B abort If Vmregion==Vmdebug then VM_DBABORT is set, otherwise _BLD_DEBUG enabled assertions abort() on failure. .TP .B break Try sbrk() block allocator first. .TP .B check If Vmregion==Vmbest then the region is checked every op. .TP .B free Disable addfreelist(). .TP .B keep Disable free -- if code works with this enabled then it probably accesses freed data. .TP .BI method= method Sets Vmregion=\fImethod\fP if not defined, \fImethod\fP (Vm prefix optional) may be one of { \fBbest debug last profile\fP }. .TP .B mmap Try mmap() block allocator first if .B break is not set. .TP .BI period= n Sets Vmregion=Vmdebug if not defined, if Vmregion==Vmdebug the region is checked every \fIn\fP ops. .TP .BI profile= file Sets Vmregion=Vmprofile if not set, if Vmregion==Vmprofile then profile info printed to file \fIfile\fP. .TP .BI start= n Sets Vmregion=Vmdebug if not defined, if Vmregion==Vmdebug region checking starts after \fIn\fP ops. .TP .BI trace= file Enables tracing to file \fIfile\fP. .TP .BI warn= file Sets Vmregion=Vmdebug if not defined, if Vmregion==Vmdebug then warnings printed to file \fIfile\fP. .TP .BI watch= address Sets Vmregion=Vmdebug if not defined, if Vmregion==Vmdebug then \fIaddress\fP is watched. .P Output files are created if they don't exist. \fB&\fP\fBn\fP and \fB/dev/fd/\fP\fIn\fP name the file descriptor \fIn\fP which must be open for writing. The pattern \fB%p\fP in a file name is replaced by the process ID. .P .B VMALLOC_OPTIONS combines the features of these obsolete environment variables: { \fBVMCHECK VMDEBUG VMETHOD VMPROFILE VMTRACE\fP }. .SH RECENT CHANGES \f3Vmlast\fP: allocated blocks are now allowed to be resized (09/1998). .SH SEE ALSO \fImtreplay\fP(1), \fImalloc\fP(3). .SH AUTHOR Kiem-Phong Vo, kpv@research.att.com