The CMemScav Library 
 
Introduction 
 
The CMemScav library, together with its header files, is the core of C Memory Scavenger. Although the Monitor provides a powerful graphical tool both for collection of memory leaks as well as for assembling calls to the library, strictly speaking, this program is not necessary for the functionality (but for the user friendliness). Contrary to the Monitor, the CMemScav library could very well be part of the final version of a product of yours. 
 
Memory Functions that C Memory Scavenger Monitors 
 
C Memory Scavenger monitors most of the memory allocation and deallocation functions. Here follows a full list over which functions are supported. 
 
Common Windows & Solaris memory functions 
  • malloc 
  • calloc 
  • realloc 
  • strdup 
  • free 
  •  
    Windows specific memory functions 
  • wcsdup 
  • mbsdup 
  • GlobalAlloc 
  • LocalAlloc 
  • HeapAlloc 
  • HeapRealloc 
  • GlobalFree 
  • LocalFree 
  • HeapFree 
  •  
    Solaris specific memory functions 
  • valloc 
  • memalign 
  •  
    Note that the C++ specific new/delete is not supported. Note also that only explicit calls to the functions in the lists above are counted. For example, in: 
     
     char *buf = getcwd(buf, 100); // getcwd will implicitly allocate 100 bytes using malloc 
     ... 
     free(buf); // Free the buffer implicitly allocated by malloc 
     
    an implicit call to malloc is done, allocating memory to buf, but will not be found by C Memory Scavenger. So, in cases like this, a call to free is necessary to prevent memory leak and here, C Memory Scavenger cannot help you. This is so, because the CMemScav library works by redefining at compilation time all malloc, calloc, free, ... functions to pass through own defined functions, before calling he original ones, to monitor all calls. However, functions that are precompiled and call memory allocating functions, such as getcwd, will prevent CMemScav from doing its job. Therefore, to have this tool to catch also calls like this, the source code of these functions need to be recompiled and linked together with CMemScav. The same goes for the C++ specific operators new/delete
     
    Header Files 
     
    There are, in total, five header files delivered with this tool. Normally, only one of them needs to be included directly by the application. This is: 
     
  • CMemScav.h 
  •  
    This header file declares the tool's public functions (more about this later).  
     
    The rest of the header files are included indirectly by the first one and should not normally be of any concern for the user. However, these are: 
     
  • CMemScavOff.h 
  • CMemScavOn.h 
  • CMSCommon.h 
  • CMSPlatforms.h 
  •  
    The first two undefines/defines macros that will force all calls to the allocation and deallocation functions, to pass through some of the public methods defined in the header file CMemScav.h. This is how the tool keeps track of all allocations and deallocations. The first file undefines possible macros later defined by the second file , see Advanced Example for how to use them. The third one declares common enums and structs used both by the library and the Monitor. Finally, CMSPlatforms.h sets up some platform specific definitions. 
     
    Public functions 
     
    The public functions in the library are declared in CGarbcoll.h. However, most of these functions should not be used directly by the applications, but are called indirectly when using malloc, calloc, and so on. See CMemScavOn.h for more information. The functions of concern for the users are: 
     
    1. void CMemScavInit(BOOL on, BOOL log, const char* file, int port) 
    2. void CMemScavSet(BOOL on, BOOL log) 
    3. BigInt CMemScavGetIndex() 
    4. CMSData *CMemScavGetListEntry(enum CMSEntry) 
    5. BigInt CMemScavFreeThese(const char *file, int minLine, int maxLine, int minSize, int maxSize, X threadId, BigInt minIndex, BigInt maxIndex) // where X = DWORD for Windows and X = pthread_t for Solaris 
    6. BigInt CMemScavFreeAll() 
    7. void CMemScavShowStatus(enum CMSStatusCountType type) 
    8. void CMemScavShowList() 
    9. void CMemScavFinish() 
    10. void CMemScavVersion(int *majorVersion, int *minorVersion) 
     
    where BigInt = __int64 for Windows and BigInt = long long for Solaris. To start using C Memory Scavenger, include the two header files at the top of this page. Now to the public functions again. 
     
    1. To initiate CMemScav, this function should be called once in the program. Any memory allocation/deallocation done before this call will not be caught by CMemScav. By the first argument, CMemScav is put in an enabled or disabled position, that is, whether or not CMemScav should track all allocations or only let them pass by. Normally, TRUE is used. Only memory calls done while CMemScav is in enabled position are caught. The second argument controls whether or not relevant information about what CMemScav does, should be logged. Normally, FALSE is used. The third argument, if not NULL, is the name of the log file. If NULL, stdout is used for logging. Finally, the last argument is the port number to communicate with the Monitor. If port > 0, this is the port number to be used. If port == 0, the default port number 5913 will be used. If negative, no socket communication will be setup. This is the normal way when you have finished using Monitor and got the other calls you need to CMemScav to clean up the memory leaks, but port must be >= 0 if Monitor should be used. 
    2. Here you can change the first two settings in CMemScavInit at any time. 
    3. Every time a memory allocation is done, an index is increased by one and associated with this allocation. With CMemScavGetIndex you can get this index's value. This value is named 'Index' and is shown in Monitor in the detailed list. This value can be used in the next function, to fine tune which allocations should be freed. See also the Advanced Example, how this function may be used. 
    4. With this function, you may traverse the Detailed List of Outstanding Memory Allocations, i.e., the same information as is found in the lower right corner of the Monitor. To get data about the first monitored allocation, enter the CMSEntry value EntryInit. To get the next ones, enter the CMSEntry value EntryNext. CMemScavGetListEntry returns a pointer to a struct called CMSData, as long there is more data to get, then a NULL pointer is returned. The CMSData struct contains all information about an allocation. See the header file CMemScav.h for the definitions of these structs. NB! Do NOT free any memory those CMSEntry structs contain. This is internal memory used within CMemScav and will be freed by CMemScav itself. 
    5. This is the key function to create calls that will clear memory allocations not needed any more. It takes 8 arguments and are used to narrow down the allocations to be freed. If file != NULL, only allocations done in this file will be cleared (full path assumed). If maxLine > 0, only allocations done at lines between minLine and maxLine, inclusive, will be cleared. If maxSize > 0, only allocations done of memory sizes between minSize and maxSize, inclusive, will be cleared. If threadId > 0, only allocations done by the thread whose thread id equals threadId will be cleared. If maxIndex > 0, only allocations done with index between minIndex and maxIndex, inclusive, will be cleared. This function is most powerful to clear certain amount of memory, which will be described in the code examples. For example, CMemScavFreeThese(NULL, 0, 0, 0, 0, 0, 0, 0) will clear all outstanding memory, and is the same as CMemScavFreeAll()
    6. See the last sentence in the item above. 
    7. Reports a summary of allocations. If the Monitor is running and is successfully connected to the application, the summary is displayed in the Monitor, both in the frame labeled "Summary of Allocations" and as a plot in the graph. If not, the summary is printed to the log chosen in CMemScavInit. The argument (defined in CMSCommon.h) could take either the  value AllCalls or OnlyOutstandingCalls. These are used to choose whether all calls should be counted when the number of calls to each memory function is added up, or if only those which presently are not yet released. Note that this argument only has effect when the summary is not displayed in the Monitor, which has a checkbox for this choice. Note that CMemScavShowStatus is a macro, calling the function InternalCMemScavShowStatus
    8. Reports a detailed list of outstandling memory allocations. If the Monitor is running and is successfully connected to the application, the list is displayed in the Monitor in the frame labeled "Detailed List of Outstanding Memory Allocations". If not, the list is printed to the log chosen in CMemScavInit. Note that CMemScavShowList is a macro, calling the function InternalCMemScavShowList
    9. When it is time to close down the usage of CMemScav, CMemScavFinish() should be called, to clean up some internal resources used. 
    10. Reports the version of the library, in two supplied integers.