MSS - Memory Supervision System Version 1.2 Documentation |
Written by Juan Jesus Alcolea Picazo, a920101@zipi.fi.upm.es and Peter Palotas, blizzar@hem1.passagen.se |
Version 1.2, Last updated 1998-11-12 |
Contents |
1. Introduction |
1.1 What is MSS? |
During the development of C/C++ programs dynamic memory is often allocated using either the standard C malloc family of functions or the C++ operators new and delete. When allocating and using dynamical memory, the programmer often make mistakes which might lead to errors during program execution, so called bugs. This could be that the program "forgets" to delete/free some memory (so called memory leaks), tries to access more memory than it allocated and a lot more. Discovering and tracking these errors is a very difficult task, and often the errors go by without the programmer noticing them because the program may appear to work correctly anyway. Therefore MSS was developed, to assist programmers in detecting such bugs and producing better programs.
MSS is a free (GPL) C/C++ library that helps you in the infamious task of finding bugs related to dynamical memory during the development of your programs. With MSS you will easily be able to detect the following bugs in your programs:
MSS can also give you a lot of information about the state of the dynamical memory allocated by your program at any point during the execution, for example:
MSS is also very easy to use. Your current sources will only require minor changes, to enable the usage of MSS.
1.2 But what does it really do? |
MSS filters all your calls to the C functions malloc(), calloc(), realloc(), xmalloc(), xrealloc(), xfree(), cfree(), free() and strdup() and if you have a C++ compiler, also the C++ operators 'new' and 'delete'. It keeps an internal list of all the allocated blocks, together with information about where the memory was allocated, how it was allocated and some other information.
All interesting events, such as memory allocations/deallocations, detected bugs and so on are written to a log file (which also may be one of the standard streams stdout or stderr) which reflects all the dynamic memory related activities of your program.
You are also provided with a set of functions to control various features of MSS, and to get some interesting info in run-time, such as maximum used dynamic memory since program start and a lot of others.
You can also check that allocated memory blocks are still valid (constant blocks), that no out of range writings has occured. You can check if a certain pointer points to a valid block of memory, and a lot of other things.
When you are ready to release your project you do not have to remove all calls to the MSS function calls, because they will all compile away to nothing if you have not defined the symbol "MSS" to the preproccessor.
1.3 Does it work with my compiler? |
MSS was written with the intention of being fully portable to any compiler/platform that supports the ANSI C/C++ standard. Since the C++ ANSI standard was just recently finished however, there are a lot of diffrent C++ dialects out there, and some may not be fully compatible with the C++ section of MSS. Some configuring options were therefore added to make MSS support as many compilers as possible. The C section of MSS however, should be fully ANSI compliant and therefore work with all ANSI compatible C compilers, with only minor configuration.
MSS was written using GCC 2.7.2.1, and has also been tested using GCC 2.8.0, GCC 2.8.1 and EGCS-1.1 and it compiles without any problems on these compilers. This also goes for the excellent DJGPP, the DOS port of GCC (with which MSS actually was developed). If your compiler is a 32-bit compiler for the i386 family of processors, building MSS should be no problems, other platforms are untested, but any reports of successful (or unsuccessful) usage of MSS are very welcome.
Currently there are two "makefiles" supplied with this package. One makefile was written for usage with the GNU C/C++ compiler (GCC) and GNU Make. (It will also require the GNU Fileutils for some operations), this is called "Makefile". The other one is a project-file for Borland C++ 5.02, composed by Rolf F. Katzenberger, this one is called "borland.ide". However we really would like to include more makefiles with MSS, so if you have another compiler, and are able to write a makefile for it, please do so and send it to us. We will be glad to include it in our next release.
If you use another compiler, and can't seem to get MSS to work with it, don't hesitate to contact us. We will do everything we can to help you.
1.4 Do I have to pay for MSS? |
No, you will never have to pay anything for using MSS. MSS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
1.5 Where can I get the latest version of MSS? |
The latest version of MSS can always be found at http://hem1.passagen.se/blizzar/mss/index.html.
MSS is also available from various FTP-sites. Among others it should be available from ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2tk/mss12.zip and ofcourse from any other simtelnet mirror. Note that it is not a DJGPP specific version, but it will (should) work with any ANSI C compliable compiler.
2. Compiling and Installing MSS |
2.1 Unpacking the archive |
You have to unpack the archive preserving the directory structure. Depending on your platform there are diffrent was to do this, but under linux the 'unzip' program automagically preserves the directory structure, and in DOS you should specify the '-d' switch to 'pkunzip'.
Start by unpacking the archive in a proper directory, under DJGPP we recommend "%DJDIR%/contrib/", i.e. the contrib directory in the directory where you installed DJGPP, usually 'C:\DJGPP\CONTRIB\' or something like that.
pkunzip -d mss12.zip or unzip mss12.zipMSS will unzip itself into its own directory, './mss12/' (under DJGPP this will be %DJDIR%/contrib/mss12 if you followed the above recommendation), so there is no need to create a separate directory for MSS before unzipping the archive.
If you are using GCC, either under DOS or Linux this is a pretty easy task.
2.2 Configuring MSS for your compiler |
There are some configuring options available to make MSS more portable to diffrent compilers. These options can be found in the file `mss.h´, and consist of preprocessor directives (#define
statements) in the beginning of the file (all marked clearly with comments). Some options may need to be defined to a specific value, and others control the behaviour of MSS by being enabled/disabled which is achieved by commenting out a #define
statement, or leaving it uncommented.
The following options may be configured in `mss.h´:
MSS_PTR_SIZE_T |
This option must be defined. It should be defined to an integer type that is large enough
to hold the value of a pointer. Default value for this is size_t . |
MSS_PRINTF_SIZE_T |
This option must be defined. It should be defined to a type specifyer string constant that will
make printf() correctly print an argument of type MSS_PTR_SIZE_T . (Ex. if MSS_PTR_SIZE_T is defined to unsigned long this option should be defined to "%lu" |
MSS_FUNCTION_MACRO |
This option must be defined. It should be defined to a predefined macro,
or a string variable provided by your compiler that represents the name of the function in which it
was found. (Set it to a string constant in case your compiler doesn't provide such a macro, ex. "unknown").
(GNU C Uses __PRETTY_FUNCTION__ or __FUNCTION__ ), and by default it is defined to __PRETTY_FUNCTION__ .
Borland users need to change this to "(unknown function)" or "?" or something, since Borland does not supply such
a function macro. |
MSS_DEFINE_NEW_DELETE_ARRAY |
Some compiler needs a redefinition of new[] and delete[], some don't (these should be rare nowadays). If your compiler does, define this, otherwise don't (comment it out). GCC wants this defined, whereas Microsoft Visual C++ 1.5 does not. If you do not know wether or not your compiler wants this defined, try compiling with this option enabled first, and disable it only if it doesn't work. |
MSS_USE_EXCEPTIONS |
This should be defined if your compiler supports exceptions. If you get a warning/error about operator delete throwing diffrent exceptions (or something like that) try toggeling this, that should help. (GCC 2.8.0 supports exceptions and wants this enabled, earlier versions does not. (With PGCC-2.90.23 based on EGCS 1.0.1 this should be defined). Anyway, if you get the errors above, try undefining this if defined, and defining it if undefined. (If you're not compiling with C++ support, you don't need to worry about this). |
MSS_DTOR_AFTER_ATEXIT |
This option should be defined in case your compiler will run the destructors of global objects after any functions registered with the atexit() function. It is not essential that this setting is correct for MSS to work, but it will make the logfile look nicer. If your compiler is advanced enough to follow the C++ standard that says that any "exit functions", including both destructors of global objects and functions registered with atexit should be called in the reverse order that they were registered, i.e. they will be mixed. In that case you will just have to test by toggling this option and see what gives the nicest looking result. Remember, whatever setting you choose for this option, it will never lead to a sever error or crash. |
MSS_DISABLE_THREADING_FUNC |
These options must be defined. They are useful in multithreading environments. They should point to a function disabling respectively enabling threading. This is not a very good solution, and it is likely to change in the future, but at present it's all there is to make the program threading safe. These are defined to nothing by default. |
2.3 Compiling and installing MSS using GCC |
Since MSS was developed using GCC, and comes with a makefile for GCC, this should not be any problems, unless you use a really old version of GCC. You might however need to configure MSS before compiling, changing one of the compiler-specific options.
NOTE! If you have GCC but not G++, the GNU C++ compiler, you will want to uncomment the 'NOCPP=.' line in the makefile (Remove the '#' sign in front of that line). If you have C++ support however, do not uncomment that line, even if you are only going to use the library in plain C projects.
Enter the MSS directory, and enter 'make all'. This should compile everything, making the library and test programs.
If you want to install the package to its default locations which are:
LIBDEST
and INCLUDEDIR
parameters under
the correct section.
There are a few more rules in this makefile, of which all are listed here.
make all
make lib
make test
make install
make clean
make cleanall
make uninstall
make fixlibc
MSS comes with a few documented sample programs that will show you some of MSS's capabilities and how you might use MSS to locate bugs. These files are located in the samples directory. See the file README
in that directory for more information.
2.4 Compiling and installing MSS using Borland C++ 5.02 |
The directory MSS was installed to is further called the MSS root directory.
Locate mss.h
in the MSS root directory and open it. Comment out the definition
of MSS_FUNCTION_MACRO
and replace it by #define MSS_FUNCTION_MACRO "(unknown function)"
.
Targets in the project file
Now open borland.ide
in your IDE. You will notice eight target nodes plus one
source pool node:
mss32.lib |
MSS library, no debugging code |
mss32MT.lib |
MSS library, no debugging code, multithreaded* |
mss32debug.lib |
MSS library, with debugging code |
mss32MTdebug.lib |
MSS library, with debugging code, multithreaded* |
test1_1.exe |
MSS test program as included in the MSS relase |
test1_2.exe |
MSS test program as included in the MSS relase |
test1_3.exe |
MSS test program as included in the MSS relase |
test2_1.exe |
MSS test program as included in the MSS relase |
MSSSources |
source pool referenced by all lib targets |
All test programs get linked with mss32.lib. I have tested mss32debug.lib, too, but none of the multithreaded libs. Also, I haven't tried to build 16-Bit libs, just in case you might wonder.
* Please note that you have to modify mss.h
to deal with multithreading. See the
details on MSS_DISABLE_THREADING_FUNC and
MSS_ENABLE_THREADING_FUNC. Without that modification, the multithreaded
libraries might not work.
Configuring the project file
Under "Options | Project | Directories" adjust the "Include" and "Library" directories so that they match your environment. If you have set an environment variable BCROOT to contain the root directory of your environment, then you don't need to make any modifications. Otherwise you have to replace each occurence of $env(bcroot) by that root directory, e.g. c:\bc5.
Compiling
In the MSS root directory, you will have found two subdirectories "lib" and "objs". Each of these directories contain a directory named "borland". These subdirectories will contain the *.obj and *.lib files. (Should you ever want to change these locations, be sure to adjust the "Intermediate" and "Final" directories under Options | Project | Directories accordingly).
Now run "Project | Build all" to compile all libraries and test programs. Please note that all object files are written into the same directory, so just running "Project | Make all" would produce corrupt libraries.
After that, all *.lib files can be found in the "lib\borland" subdirectory. All test executables can be found in the "samples" subdirectory.
If you have trouble compiling MSS under Borland C++ v5.02, please feel free to mail me under rfkat@ibm.net. However, please direct questions directly pertaining to MSS to Peter Palotas at blizzar@hem1.passagen.se.
2.5 Compiling and installing MSS using another compiler |
If you are using another compiler, you will have to write your own makefile or compile the library manually. The library should consist of the following files:
alloc.c
check.c
cppspec.cc (only if your compiler supports C++)
list.c
inifile.c
config.c
init.c
internal.c
log.c
inifile.c
user.c
You might have to rename the .cc
files to .cpp
for some compilers. (Probably for most DOS based ones).
After compiling these files and generating the library, the library and the include file `mss.h
´ has to be copied to somewhere where your compiler will find them. Read the manual for your specific compiler.
MSS comes with a few documented sample programs that will show you some of MSS's capabilities and how you might use MSS to locate bugs. These files are located in the samples directory. See the file README
in that directory for more information.
3. Using MSS |
3.1 How to make your program use MSS |
Making your program use MSS is as we have mentioned earlier really simple. All you have to do is to add `#include <mss.h>
´ at the very top of every C/C++ source file in your project. Note that you have to add this line to all files in your project, or MSS will not work correctly. To actually enable MSS you will also have to define the symbol MSS
, and link your program with the MSS library.
If you are using GCC, you can simply define the MSS
symbol by specifying -DMSS
on the commandline to gcc, and specify -lmss
to link with the MSS library. To achieve best performance, you should specify the MSS library as the very last library on the commandline. This is because MSS wants to know when your program exits, and if you don't specify MSS as the last library, it might think your program exits before it really does, due to the way destructors are called. (This does not affect C projects though, nor will it cause any errors or anything, it will just print that the program exits before it really does to the log file, hence making it look like some allocations/deallocations occured after the program exit. This is extremely rare though, and you normally don't have to worry about this).
Every call to 'new
', 'delete
', 'malloc
', 'calloc
', 'realloc
', 'xmalloc
', 'xrealloc
', 'cfree
', 'xfree
', 'free
' and 'strdup
' will be filtered and processed by MSS, and a logfile will be
created. (Or logging will be written to stdout/stderr, depending on your configuration). You might notice a minor(?) speed
degradation when running your program using MSS (sometimes, depending on how MSS is configured, the speed degradation can be very big, which might make you think the program has crashed), otherwise you shouldn't notice anything diffrent about your program. (Other than the fact that you probably will get fewer crashes). The logfile created will contain information about all allocated memory, when the allocations/deallocatios occured, if any errors has been detected and so on. Depending on the configuration options to MSS the logfile can sometimes become very large, so be aware of this so that you have enough free diskspace.
3.2 Functions provided by MSS |
MSS provides a lot of functions that your program might call to get information about the current memory situation, or affect the logging in some way which is what most of the functions do. All functions are called through macros, which all compiles away to nothing in case the preprocessor symbol 'MSS
' was not defined. This feature makes it easy to switch between "debug" and "release" mode, in case you want to for an example test the real speed with which your program will run this comes quite in handy.
For a complete reference of all the functions, see the Function Reference.
3.3 What do those warnings in the logfile really mean? |
The MSS logfile sometimes produces warnings which may seem strange at first, therefore we have decided to explain the meaning of some terms here.
Prefix Corrupted | You have written some data out of the limits of the described block. Specifically, you've done it before the start of the block. This is mainly caused by using 'signed' numbers as array indexes or pointer displacements on some pointer arithmetic, so you end up using negative indexes or displacements. |
Suffix Corrupted | You have written some data out of the limits of the described block. Specifically, you've done it after the end of the block. This is typically caused by array operations contained in loops that go 'too far'. Can also be caused by using a too small buffer to hold some data. |
Trying to delete a non-allocated block | There is no block allocated at the address that pointer points to. The main reasons for this are:
|
There is no block starting at 'address' | Same as above. This is issued when you request some info about a non existent block. |
Zero length allocation | You are requesting an allocation for a zero length block. Maybe some uninitialized variable or a logic or flow bug is causing this problem!? |
NULL pointer deallocation | You are deleting a pointer to NULL. This will probably result in a GP Fault, however it is actually legal in C++ (using delete) a warning will still be printed, since you shouldn't do this. Some compilers may not like it! (This warning can be disabled for C++ though, but is normally enabled). |
Pointer 'p' does not point to any valid memory | You are dealing with a pointer that does not point to any legal allocated memory. MSS should tell you also what are the nearest legal blocks. You've probably stepped out from any of them. You may also be using an uninitialized pointer. |
3.4 Hints & Tips |
Here are some notes that you may find useful:
README
' in the samples
directory for more information.
MSS_CHECK_ALL_BLOCKS
or MSS_CHECK_BLOCK_AT()
) or if CheckOnDealloc
or CheckAllOnAlloc
is enabled at compile time.
MSS_DISABLE_LOG_OUTPUT
at the beginning of your program. This will make MSS log only the warnings, and not every legal memory operation. Anyway, it is a good practice to inspect at least once the 'memory allocation trace' generated by MSS by default. If you get a warning about trying to delete a non allocated block, enable FillMemOnAlloc
and take a look at the direction of the offending pointer; if it is equal to FillMemOnAllocValue
, then you are deleting a dynamically allocated uninitialized pointer. 0x98 is the default FillMemOnAllocValue
.
#include "ctree.h" //For complex tree class #include "mss.h" //For MSS :) int main(void) { Ctree * my_tree= new Ctree; //I create a complex tree <...Do a lot of operations of node insertion...> MSS_LOG_INFO; //To see number of blocks and memory used. delete my_tree; //Destroy the tree -> call destructor -> release memory MSS_LOG_INFO; //To see if there is still any allocated memory. MSS_LOG_BLOCK_LIST; //To get detailed info about it. return 0; } |
#include <mss.h>
in ALL your C files to fully use MSS, or if you want to stop using MSS, you can either delete all #include <mss.h>
, or not define 'MSS'. You also must not link the MSS library to your project. (If you are using only plain C, no C++, you can still link the library if you want to, making it very easy to disable MSS. Simply don't define 'MSS
'). If you forget putting #include <mss.h>
in any of your project's C++ files, MSS will not be able to get detailed info about memory allocations or deallocations (I mean line number, module name and function name), but it will still handle all loggings correctly. This loggings will appear as: "LOG: unknown (line 0 of unknown) allocated 20 bytes at 51120.
".mss.h
´ in your C files MSS will not intercept and detect any allocations/deallocations.
3.5 Known problems with MSS |
Currently there is only a few serious known problem with MSS. If your program overloads the operator new
your program will not work correctly with MSS. Also if you make your own #define free <something>
or
any other allocation function MSS will not work. Currently we have no good solution to these problem, but if you come up with
anything, please contact us.
4. Configuring MSS |
4.1 General information. |
This chapter discusses the configuration which affects MSS while it is running, which mostly includes what kind of error checking to perform, and the layout of the logfile.
All compiler specific configurations should be made either in the makefile (if you are using GCC) as discussed in Compiling and installing MSS using GCC, or in `mss.h´ which is discussed in Configuring MSS for your compiler.
All run-time specific configurations are either read from special configuration files at run-time, or the internal hard-coded values are used. The special configuration files does not need to contain all available configuration options, only the ones that it should override. The configuration is made in the following order;
There is no need to have any configuration file present, and in that case the hard-coded values are used. If you wish to use a global configuration file, this file will be read by any program that uses MSS, the environment variable `MSS_CFG
´ should contain the full path to this file. The option `LocalCFGFile
´ in this file specifies the name of the local configuration file (if this option is not available the hard-coded value `mss.cfg
´ will be used. The local configuration file is always expected to be found in the directory from which the program is run (NOTE that your program must not change directories before the first call to an MSS function or a memory allocation function if the local configuration file should be found). If this files exists, any options available in it will override the options previously read from any global configuration file or the hard-coded values.
Please note that you do not need to have both configuration files present. You can choose only to have the local or the global file or none of them. It is however recommended that you create a global configuration file, so that you are sure on which options are enabled.
4.2 Configuration file syntax |
The syntax of the configuration files is really simple, and is very similar to for an example the windows ini files except there are no sections. The purpose of the configuration files are to set various options to diffrent values. The general syntax is:
<OptionName> = ["]<Value>["]
<OptionName>
is the name of the option, and <Value>
is the value you wish to set this option to. The value can be quoted if you wish to, but this is not neccessary unless you want to include whitespaces at the beginning or the end of the value. There are some values that have a special meaning if a boolean (true/false) value it expected. You can set a boolean option to either "True", "1" or "Yes" to specify a true value, or "False", "0" or "No" to specify a false value. Note that all integer values can be specified in decimal or hexadecimal form (ex. 0x10
). If you want the option to include a quote ("), a newline or some other special character you need to escape it. The following escape codes are recognized by MSS:
Escape Sequence | Meaning |
\\ |
Single backslash |
\n |
Newline |
\r |
Carriage Return |
\" |
Double Quote |
\t |
Tab |
Comments are also allowed in the config file, on an empty line. They should be preceeded by a #
-sign.
Let's show you an example:
# This is a comment LogFileName = "mss.cfg" # False and No have the same meaning. LogToStdout = False LogToStderr = No NewLineString = "\n" |
NOTE! The configuration files are case-insensitive, that is "LogFileName" is equal to "LOGFILENAME" and "logfilename".
4.3 Specifying where to write log output |
Logging output can be written either to a file, or any of the standard output streams (stdout and stderr). This is controlled by the three configuration options `LogFileName
´, `LogToStdout
´ and `LogToStderr
´.
Option Name | Type | Description | Default |
LogFileName |
String | The filename to which logging output will be written in case both `LogToStdout ´ and `LogToStderr ´ are set to false. They are described below |
mss.cfg |
LogToStdout |
Boolean | If this is set to true logging output will be written to the standard output (stdout). Note that only one of `LogToStdout ´ and `LogToStderr ´ may be set to true at the same time, so always include both of these in the configuration file. |
False |
LogToStderr |
Boolean | If this is set to true logging output will be written to the standard error (stderr). Note that only one of `LogToStdout ´ and `LogToStderr ´ may be set to true at the same time, so always include both of these in the configuration file. |
False |
4.4 Options concerning error detection |
There are a number of options that lets you specify diffrent methods which will either make MSS detect errors, or somehow make it easier for the programmer to detect them. They are listed below:
Option Name | Type | Description | Default |
WatchLimits |
Boolean | This option enables/disables the checking of out-of-bounds writes on dynamically allocated memory blocks. This is achieved by allocating some extra space on both sides of the memory block, and filling it with a specific value. Then upon deallocation of the block, or upon request from user, this extra space is checked. If it doesn't all contain the same value it was filled with then an out-of-bound writing has occured. It is recommended to have this option enabled. Although it wastes some memory, it is one of the most powerful features in detecting bugs. | True |
WatchSize |
Integer | This option specifies the size of the extra space allocated before and after any allocated blocks, if `WatchLimits ´ was set to true. Bigger values give more detection power, but also more waste of memory and the time spent checking blocks will increase. |
32 |
WatchValue |
Integer (0-255) | This option specifies the value with which the extra space allocated before and after any allocated blocks if `WatchLimits ´ was set to true. Set this to anything but zero. |
0xA8 |
FillMemOnAlloc |
Boolean | If this option is set to true, all memory allocated will be filled with a specific value (specified by `FillMemOnAllocValue ´). This is useful, since programmers often accidently rely upon uninitialized memory, which usually will be zero, but with this option enabled it will all be initialized to `FillMemOnAllocValue ´ |
True |
FillMemOnAllocValue |
Integer (0-255) | This option specifies the `byte´ value with which to fill memory upon allocation. (see `FillMemOnAlloc ´) |
0x98 |
FillMemOnDealloc |
Boolean | If this option is enabled all memory will be filled with a specific value (specified by `FillMemOnDeallocValue ´ upon deallocation. This is useful, since programs often use memory after it has been deallocated (it even happened during the development of MSS, but we had a much harder time detecting it than you will have with this option enabled), and with this option
enabled those bugs will be easy to detect. |
True |
FillMemOnDeallocValue |
Integer (0-255) | This option specifies the value with which to fill deallocated memory with. (see `FillMemOnDealloc ´). |
0x86 |
CheckOnDealloc |
Boolean | With this option enabled all blocks will be checked for out-of-bound writings and constant block corruption as they are deallocated. It is stronglyrecommended that you leave this enabled, since all blocks really should be checked upon deletion. | True |
CheckAllOnAlloc |
Boolean | If this option is set to true all blocks will be checked for out-of-bound writing and constant block corruptions every time a block is allocated/deallocated. This can be very time-consuming, and is usually not neccessary. | False |
AllocFails |
Integer (0-100) | This option should be a number between 0 and 100, which indicates how many percent of the times that malloc are called will fail, hence returning NULL. This is useful for stress-testing you application, to see if it can deal with out-of-memory situations. If this is set to ex. 50, malloc/calloc/realloc will return NULL about every second time it was called (average), even though they did not actually run out of memory. Set to zero to disable. | 0 |
ExitOnWarning |
Boolean | If this option is enabled, MSS will exit the program as soon as a warning is written to the logfile. This option is disabled by default, but if your program crashes, and the logfile somehow disappears it might be useful to enable this option. | False |
WarnOnAllNULLDeallocs |
Boolean | If this option is set to true, MSS will always warn you when trying to deallocate a NULL-pointer using the The reason this warning can be disabled, is because it is legal to deallocate a NULL-pointer according to the ANSI C/C++ standard. However, some compilers do not like this, and crash if you try to deallocate a NULL-pointer, so it's always good practice to check for NULL-pointers before deallocating memory. | True |
ZeroLenAllocReturnNULL |
Boolean | If this option is set to true, MSS will always return NULL if the user program tries to allocate a block sized zero bytes, rather than passing the request to the standard library allocation function. It is recommended to have this option enabled, and it is by default. | True |
4.5 Options concerning the layout of the logfile |
There are also a couple of options that controls the layout of the logfile, they are listed here.
Option Name | Type | Description | Default |
ShowLogs |
Boolean | With this option enabled all normal log messages (successful operations) will be written to the logfile, if it's disabled no normal log messages will be written to the logfile. (This can be overridden by function calls, see the Function Reference). | True |
ExtraNewline |
Boolean | If this option is enabled, there will be an extra newline written to the logfile, between each log/warning message. This will make the logfile more readable. | True |
WordWrap |
Boolean | This option defines wether or not the logfile should be word-wrapped. | True |
5. Function Reference |
5.1 General information |
MSS provides a number of functions, that either controls the behaviour of MSS or outputs some information to the logfile. All calls are made through macros, and all of these macros expand to nothing if the symbol `MSS
´ was not defined, which is useful for switching between "debug" and "release" mode when compiling your program. (Don't forget not to link the mss library with your program if you are using C++ and want to test a "release" version of your program).
Note that the MSS macros should not have any parenthesis after them in case the function takes no arguments. See this example:
char *ptr = new char[10]; strcpy(ptr, "Hello"); MSS_DISABLE_LOG_OUTPUT; MSS_REGISTER_CONSTANT_BLOCK(ptr); MSS_ENABLE_LOG_OUTPUT; ... |
As you see the `MSS_DISABLE_LOG_OUTPUT
´ macro is called without any trailing empty parenthesis ().
5.2 Reference |
This is the MSS function reference. (Actually macro reference, but all macros call functions so...)
Function name | Description |
MSS_LOG_INFO |
This command writes general info about the present memory state to the logfile. The info written is:
Please note that all memory references done by MSS are about dynamically allocated memory, MSS does not proccess static or automatic memory usage. |
MSS_LOG_INTERNAL_INFO |
This command lists some information about how much memory MSS actually uses, how much memory is wasted by the ` |
MSS_LOG_BLOCK_LIST |
This command outputs a list of all currently allocated blocks to the logfile, together with information about where that block was allocated, by what function, the size of it and so on. A little warning is probably in place though, the output can be quite long if there is a lot of blocks allocated. (Just look at the test programs). |
MSS_LOG_BLOCK_LIST_FILTERED(func) |
This command iterates through the list of currently allocated blocks, and calls a user-supplied callback function for each block. This allows for selective inspection of block contents or selective block lists. The user-supplied callback function must be of the following type: int callback_func(char *out, void *block, unsigned int size, const char *label, const char *file, const char *function, unsigned int line); where block is a pointer to the block, size is the size of the block, label is a string containing the label of the block if any has been set, or NULL otherwise, file, function, line represents the file, line and function in which the block was allocated. (The function might not be correct if your compiler does not support a FUNCTION macro).All the output of this function that you want written to the logfile should be written into out which points to an empty string. (see Sample 2 for an example).Exactly what the callback function does is not relevant as long as:
|
MSS_CHECK_ALL_BLOCKS |
This command checks all allocated blocks for out-of-bound writings and corrupted constant blocks. This command is only effective if MSS was compiled with the WatchLimits option enabled (see Configuring MSS). |
MSS_CHECK_BLOCK_AT(ptr) |
This command checks the specified block starting at `ptr ´ for out-of-bound writings and if block was registered at constant also for corruption. This command is only effective if MSS was compiled with the WatchLimits option enabled (see Configuring MSS). |
MSS_CHECK_POINTER_VALIDITY(ptr) |
This command tells you if the specified pointer `ptr ´ points to a legal (dynamically allocated) block of memory (not only the start of the block, but anywhere in a block). If not this command will write the nearest block start and block end, and the distance (in bytes) from the pointer to both start and end to the logfile. |
MSS_LOG_MSG(str) |
This command simply writes the specified string `str ´ to the logfile. |
MSS_DISABLE_LOG_OUTPUT |
Disabling log-output prevents all legal allocation or deallocation messages to be written to the log file. They are processed by MSS, but silently. Warnings and command outputs are still written anyway. |
MSS_LOG_MSG(str) |
This command simply writes the specified string `str ´ to the logfile. |
MSS_STARTUP |
This command initializes MSS. It is good practice to use this in the very beginning of your program, however not neccessary. If you are registering a function with atexit() before doing any memory allocations though, it is strongly recommended that you put this command before the call to atexit. |
MSS_SET_BLOCK_LABEL(ptr, str) |
This command will give the block pointed to by `ptr ´ the label specified by `str ´. This label will then be written to the logfile whenever a warning/message is written that involves this pointer. This is useful for keeping track of pointers. |
MSS_DUMP_BLOCK(ptr, filename) |
This command will generate a raw binary dump of the memory contents pointed to by `ptr ´ and write it to the file specified by `filename ´. |
MSS_REGISTER_CONSTANT_BLOCK(ptr) |
These commands registers/unregisters the block starting at `ptr ´, as a constant block. When a block is registered as constant it means that the contents of that block may not be changed, and MSS will print a warning if they are, the next time this block is checked. This function uses a very simple checksum method, that simply adds all the bytes in the block together. This is not very bullet proof, but the chance is pretty big that a bug will be detected by this method. |
MSS_ENTER_SCOPE |
These commands are useful, if you want to make sure that all blocks that are allocated within a scope are deallocated at the end of that scope. Simply enclose the scope you want to check with ` (This function only checks the number of allocated blocks, so it might fail to detect a bug the way you want it, however this should be quite unlikely). A warning will be printed at the termination of the program (or what MSS believes is the termination of the program anyway) if
the number of |
Function name | Description |
MSS_CURRENTLY_USED_MEM |
Returns the amount of currently allocated memory, not including the extra memory wasted by MSS internally. |
MSS_MAXIMUM_USED_MEM |
Returns the maximum amount of allocated memory since program start, not including the extra memory wasted by MSS internally. |
MSS_NUMBER_OF_ALLOCATED_BLOCKS |
Returns the number of allocated blocks. |
6.History |
6.1 The birth of MSS |
MSS was born, just like a lot of other programs, as a private tool created by Juanje to check the dynamic memory activities of a game he's writing. The game was growing, and he was feeling a little lost in a forest of allocations/deallocations. At first it was only an overload of the C++ oprators `new
´ and `delete
´ that counted the amount of memory used. Then, he had the idea of upgrading it and adding some other features. By those days, he found a similar program called FORTIFY. He took a look at it and found it great. But it didn't work for him (why?). So he decided to create MSS and improve it with some of the features found in FORTIFY. He did it in a couple of days. It was August '97.
Then Peter discovered a bug, that MSS didn't detect memory activites that occured before main, like in global object constructors. So he sat down and fixed this in a couple of days, but the solution still wasn't good enough he thought, so he decided to make a better solution by rewriting the entire MSS in ANSI C. And after he did that he added some more features, discovered some more bugs, and modified it all again, and spammed Juanje with e-mails about all the things he had done, although he knew Juanje was too busy with his exams to even check his mailbox! After he had done all that, he decided to rewrite the documentation, since so many changes were made... It was January '98, and MSS did not look anything like the first betas that Juanje first released.
Finally, Peter and Juanje started working together on MSS, hardtesting it and adding new features, preparing the first real release of MSS, it is February '98.
Then Juanje got too many other things to attend to, to continue the development of MSS. Peter worked for a couple of weeks, but then he too could not work with MSS anymore. So there was version 1.1 lying on Peter's HDD without being released until August '98. Now Peter got a mail from a guy with a question about MSS, and he decided to release the new version of MSS, version 1.1.
6.2 Changelog |
First public release: It was called SENTINEL, but there is a commercial product with this same name, so it had to be changed. Sorry if this caused any confussion or inconvenience.
September 97:
October 97:
November 97:
December 98:
January 98:
January 98:
February 98:
config.h
´, and added support for run-time configuration files.April 98:
MSS_PTR_SIZE_T
and MSS_PRINTF_SIZE_T
was added).MSS_LOG_BLOCK_LIST_FILTERED
, thanks to Olaf Stoyke for contributing with this function.November 98:
6.3 To-Do |
We are working our way down the To-do list, and not many things are here right now. If you are missing some feature in MSS and you can't find it in this list, please send us a comment. Any suggestions are appreciated.
7. Contacting the authors |
7.1 General info |
MSS was written by Juan Jesus Alcolea Picazo, a920101@zipi.fi.upm.es and Peter Palotas, blizzar@hem1.passagen.se
Any comments, suggestions and bugreports are very welcome. Please direct all such e-mails to Peter, since Juan are not currently working on MSS.
7.2 Submitting a bug-report |
If you are going to submit a bug report, the best thing you can do is to send us the logfile and the smallest source code possible to reproduce the bug. The second best thing to do is to send us the entire source-code to your program (if the source < 50K). If the source code is large or you don't want to send it to us by some other reason, just send us the logfile and we'll see what we can do.
And ofcourse, tell us what the problem is and what version of MSS you are using!
8. Copyright |
MSS -- Memory Supervision System version 1.2 Copyright © 1998 Juan Jesus Alcolea Picazo and Peter Palotas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. (See also Contacting the Authors). |