Library-level dynamic memory allocation provides an easy-to-use interface for dynamic memory allocation.
The following interfaces are used most often:
malloc() – Returns a pointer to a block of memory at least as large as the amount of memory that is requested. The block is aligned to store any type of data. For more information, see the malloc(3C) man page.
free() – Returns the memory that is obtained from malloc(), calloc(), realloc(), memalign(), or valloc() to system memory. Trying to free a block that was not reserved by a dynamic memory allocation interface is an error and causes a process to crash. For more information, see the free(3C) man page.
calloc() – Returns a pointer to a block of memory that is initialized to zeros. Memory reserved by calloc() can be returned to the system through either watchmalloc() or free(). The memory is allocated and aligned to contain an array of a specified number of elements of a specified size. For more information, see the calloc(3C) man page.
Other dynamic memory allocation interfaces are as follows:
memalign() – Allocates a specified number of bytes on a specified alignment boundary. The alignment boundary must be a power of 2. For more information, see the memalign(3C) man page.
realloc() – Changes the size of the memory block allocated to a process. realloc() can be used to increase or reduce the size of an allocated block of memory. realloc() is the only way to shrink a memory allocation without causing a problem. The location in memory of the reallocated block might be changed, but the contents up to the point of the allocation size change remain the same. For more information, see the realloc(3C) man page.
void *reallocarray(void *ptr, size_t nmemb, size_t size); – Enables callers to rely on libc to do overflow checking for the nmemb * size calculation, rather than the caller needing to do overflow checking. The routine can also be used for new memory allocations by passing NULL for the ptr argument. This behavior is similar to calloc() without zero'ing the allocated memory. For more information, see the reallocarray(3C) man page.
reallocf() – Changes the size of an allocated memory block. Unlike realloc(), if this function cannot allocate the requested size, it frees the existing block, so that programs do not have to keep track of the old address and free it themselves. For more information, see the reallocf(3C) man page.
valloc() – Allocates a specified number of bytes that are aligned on a page boundary. For more information, see the valloc(3C) man page.
The Oracle Solaris OS and Oracle Developer Studio software contain tools for finding and eliminating errors in dynamic memory use.
Oracle Solaris tools for debugging dynamic memory include the following:
watchmalloc is a debugging memory allocator library. For more information, see the watchmalloc(3MALLOC) man page.
libumem is a memory management library. You can use libumem to detect memory management bugs. libumem is a user space slab allocation library, which performs object caching that results in caching the frequently allocated and freed memory. Object caching reduces the overhead of creating and releasing the memory. You can view the information about memory cache, memory allocation, and memory corruption using Modular Debugger (MDB). For information about modular debugger, see Oracle Solaris Modular Debugger Guide.
You can also use the libadimalloc library on platforms that support ADI. The functions in the libadimalloc library provide scalable object-caching memory allocation with multithreaded application support. Also, this library uses ADI to detect buffer overrun errors, out-of-bounds pointer errors, stale pointer errors, and use-after-free errors. For more information, see the libadimalloc(3LIB) man page.
The Oracle Developer Studio tools for debugging dynamic memory include the following:
dbx is an interactive, source-level, command-line debugging tool. You can use it to run a program in a controlled manner and to inspect the state of a stopped program. dbx gives you complete control of the dynamic execution of a program, which includes collecting performance and memory usage data, monitoring memory access, and detecting memory leaks. dbxtool provides a graphical user interface for dbx. For more information, see Oracle Developer Studio 12.6: Debugging a Program With dbx.
The Run Time Checking (RTC) tool enables you to automatically detect runtime errors, such as memory access errors and memory leak, in a native code application during the development phase. It also allows you to monitor memory usage. You cannot use runtime checking on a Java code. For more information about using RTC, see Chapter 9, Using Runtime Checking, in Oracle Developer Studio 12.6: Debugging a Program With dbx.
The advanced development tool "Memory Error Discovery Tool (Discover)" can also detect memory access errors. For more information, see the Oracle Developer Studio 12.6 Discover and Uncover User's Guide.
Oracle Developer Studio is available on as a package to download and install on the Oracle Solaris OS. For more information, see the Download Options for Oracle Developer Studio.
Additional memory control interfaces include the sysconf(), mprotect(), brk(), and sbrk() functions.
The sysconf() interface returns system dependent sizes of memory pages and applications should use the getpagesizes() function to find out which memory pages are available to a running process. For portability, applications should not embed any constants that specify the size of a page. Note that varying page sizes are not unusual, even among implementations of the same instruction set. For more information, see the sysconf(3C) and getpagesizes(3C) man pages.
The mprotect() interface assigns the specified protection to all pages in the specified address range. The protection cannot exceed the permissions that are allowed on the underlying object. For more information, see the mprotect(2) man page.
A break is the greatest valid data address in the process image that is not in the stack. When a program starts executing, the break value is normally set by the execve() function to the greatest address defined by the program and its data storage.
Use the brk() function to set the break to a greater address. You can also use the sbrk() function to add an increment of storage to the data segment of a process. You can get the maximum possible size of the data segment by a call to the getrlimit() function.
caddr_t brk(caddr_t addr); caddr_t sbrk(intptr_t incr);
brk() identifies the lowest data segment location not used by the caller as addr. This location is rounded up to the next multiple of the system page size.