Main page | Documentation | Download | Development | SourceForge project page |
Memory Supervision System (MSS) is a C/C++ library for detecting dynamic memory allocation bugs.
--- The Detailed Node Listing ---
Introduction to MSS
Compiling and installing MSS
Using MSS
Configuring MSS
Function reference
Development
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 C/C++ library that helps you in the notorious 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.
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.
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, there are a lot of different 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, EGCS 1.1 and GCC 2.95.3 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.
The information on where to get the latest version of MSS is available at http://libmss.sourceforge.net.
You have to unpack the archive preserving the directory structure.
Depending on your platform there are different ways 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.
MSS will unzip itself into its own directory,
./mss12/
, so there is no need to create a separate directory
for MSS before unzipping the archive.
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
size_t
.
MSS_PRINTF_SIZE_T
printf()
correctly print an
argument of type MSS_PTR_SIZE_T
. For example, if
MSS_PTR_SIZE_T
is defined to unsigned long
, this option
should be defined to "%lu"
.
MSS_FUNCTION_MACRO
"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
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
delete
throwing diffrent
exceptions (or something like that) try toggling this, that should
help. (GCC
2.8.0 and latter support exceptions and want this
enabled, earlier versions do not). 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
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 severe error or crash.
MSS_DISABLE_THREADING_FUNC MSS_ENABLE_THREADING_FUNC
Since MSS was developed using GCC
, and comes with a
makefile
for GCC
, there should not be any problems,
unless you use a really old version of GCC
. In this case you
may need to tweak mss.h
as described in previous section.
See Configuring MSS for your compiler.
If you have GCC
but not G++
, the GNU C++
compiler, you will want to uncomment the 'NOCPP=.'
line in the
makefile
.
Enter the MSS directory, and enter make all
. This
should compile everything, including the library and test programs.
Just enter make install
, if you want to install the package to
its default locations, which are:
%DJDIR%/include
, the library
goes into %DJDIR%/lib
.
/usr/local/include
, the
library goes into /usr/local/lib
.
If you want to install MSS to another location, edit the
makefile
and change the LIBDEST
and INCLUDEDIR
parameters under the correct section.
If you are using G++
2.95.x or later, you have to replace
header file <streambuf.h>
because of incompatibility
See Known problems with MSS. For DJGPP, just copy
%DJDIR%/contrib/mss/streambuf.h
to
%DJDIR%/lang/cxx/streambuf.h
.
There are a few more rules in this makefile:
make all
lib/[linux|djgpp]/libmss.a
, and
the sample programs will be in the samples
directory.
make lib
make test
make install
/usr/local/lib/libmss.a
under
linux, or %DJDIR%/lib/libmss.a
under DJGPP, and the header
file mss.h
will go in /usr/local/include
under linux,
and %DJDIR%/include
under DJGPP. You can change LIBDEST
and INCLUDEDIR
in the makefile
(under either the DJGPP
or linux section) if you want these files installed to another place.
make clean
make clean
is run under Linux it won't remove the DJGPP
object files, and vice versa.
cleanall
make uninstall
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)"
. Also,
if you are going to use MSS with multithreaded libraries,
define MSS_DISABLE_THREADING_FUNC
and
MSS_ENABLE_THREADING_FUNC
See Configuring MSS for your compiler.
Now open borland.ide
in your IDE. You will notice
eight target nodes plus one source pool node:
mss32.lib
mss32MT.lib
mss32debug.lib
mss32MTdebug.lib
test1_1.exe
test1_2.exe
test1_3.exe
test2_1.exe
MSSSources
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
.
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.
Making your program to use MSS is as we have mentioned
earlier is 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 different 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/deallocations 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 make sure you have enough free disk space.
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. All functions are called through macros,
which compile away to nothing in the case the preprocessor symbol
MSS
was not defined. This feature makes it easy to switch
between "debug" and "release" mode.
For a complete reference of all the functions, see the Function Reference See Reference.
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
signed
numbers as array indexes or
pointer displacements on some pointer arithmetic, so you end up using
negative indexes or displacements.
Suffix Corrupted
Trying to delete a non-allocated block
There is no block starting at 'address'
Pointer 'p' does not point to any valid memory
Zero length allocation
NULL pointer deallocation
NULL
. However, current C and C++ language
standards permit this.
samples
directory. See the file README
in that directory for more
information.
WatchSize * 2
if
WatchLimits
is enabled.
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.
#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 and 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 events correctly. They will appear in a log as:
"LOG: unknown (line 0 of unknown) allocated 20 bytes at 51120."
.
The same applies to precompiled modules linked with your application.
However, this does not apply to C files. If you forget to include
mss.h
in your C files MSS will not intercept and
detect any allocations/deallocations.
Currently there is only one known serious problem with MSS:
if your program overloads the operator new
your program will
not work correctly with MSS. For example, this happens with
libstdc++
from GCC
2.95. (Workaround is described in
installation instructions See Configuring and installing MSS using GCC. Also, if you make your own #define free <something>
or any
other allocation function, MSS
will not work neither. Currently
we have no good solution to these problems, but there is a workaround
available: insert #include <no_mss.h>
before any problematic
place and re-include <mss.h>
afterwards.
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 chapter
about compiling and installing MSS using GCC
(See Configuring and installing MSS using GCC, or in mss.h
which is discussed in chapter on configuring MSS for your
compiler (See Configuring MSS for your compiler.
All run-time specific configuration information is 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:
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.
The purpose of the configuration files are to set various options to different values. The general syntax is:
<OptionName> = ["]<Value>["]Where
<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 is
expected for a particular option. 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
\\
\n
\r
\"
\t
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"
The configuration files are case-insensitive, that is
"LogFileName"
is equal to "LOGFILENAME"
and
"logfilename"
.
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 sent 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
|
There is a number of options that lets you specify different methods which will either make MSS detect errors, either 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 sentinel value. Then upon deallocation of the block, or upon request from user, this extra space is checked. If it doesn't 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 value for filling allocating memory
with, if FillMemOnAlloc is set.
| 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, if FillMemOnDealloc is set.
| 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 strongly recommended that you leave this enabled. | 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 often calls to malloc will fail, returning
NULL . This is useful for stress-testing you application, to
see if it can deal with out-of-memory situations. For example, if
this is set to 50, malloc and its family will return
NULL about every second time it was called (on average),
even though they did not actually run out of memory. Set to 0 to
disable.
| 0
|
ExitOnWarning
| Boolean | If this option is enabled, MSS will terminate 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. The reason
this warning can be disabled, is because it is legal to
deallocate a NULL pointer according to the ISO C
and C++ standards. 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 0 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
|
There are also a few options that control the layout of the logfile, they are listed here.
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 setting does not affect output by MSS function calls from user code. | 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 if the logfile should be word-wrapped. | True
|
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 make a "release" version of your
program).
Note that the MSS macros should not have any parenthesis after them in the case the macro does not take anhy 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 can see, the MSS_DISABLE_LOG_OUTPUT
macro is called
without any trailing empty parenthesis ()
.
This is the MSS function reference (Actually it is a macro reference, but all these macros are function-like)
MSS_LOG_INFO
Please note that all memory references done by MSS are about
dynamically allocated memory, MSS does not work with static
nor automatic memory usage.
MSS_LOG_INTERNAL_INFO
WatchLimits
option and so on, to the logfile.
MSS_LOG_BLOCK_LIST
MSS_LOG_BLOCK_LIST_FILTERED(func)
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
represent 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).
The callback function should meet following requirements:
out
)
out
MSS_CHECK_ALL_BLOCKS
WatchLimits
option
enabled.
MSS_CHECK_BLOCK_AT(ptr)
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.
MSS_CHECK_POINTER_VALIDITY(ptr)
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)
str
to the logfile.
MSS_DISABLE_LOG_OUTPUT MSS_ENABLE_LOG_OUTPUT
MSS_STARTUP
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)
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 tracking pointers.
MSS_DUMP_BLOCK(ptr, filename)
ptr
and write it to the file specified by
filename
.
MSS_REGISTER_CONSTANT_BLOCK(ptr) MSS_UNREGISTER_CONSTANT_BLOCK(ptr)
ptr
,
as a constant block. When a block is registered as a constant block,
it means that the contents of that block may not be changed, and
MSS will print a warning if they are, by the next time this
block is checked. This function uses a very simple checksum method,
that simply sums up all bytes in the block. This is not very
bulletproof method, but it should be sufficient for bug detecting.
MSS_ENTER_SCOPE MSS_LEAVE_SCOPE
MSS_ENTER_SCOPE
at the top and MSS_LEAVE_SCOPE
at the
end.
Function-like macros that returns a value (unsigned int
) to the
caller and prints nothing to the logfile
MSS_CURRENTLY_USED_MEM
MSS_MAXIMUM_USED_MEM
MSS_NUMBER_OF_ALLOCATED_BLOCKS
MSS was originally written by Juan Jesus Alcolea Picazo, a920101@zipi.fi.upm.es and Peter Palotas, blizzar@hem1.passagen.se. Currently they do not respond to e-mails, so Laurynas Biveinis (lauras@softhome.net) has taken over maintainership and set up project hosting at SourceForge (http://www.sourceforge.net. He will return the project to the original authors when/if one of them contacts him.
The best way to contact MSS developers is to send e-mail to libmss-devel@lists.sourceforge.net.
More information is available at the project home page (http://libmss.sourceforge.net).
The best way to report a bug is to use bug tracking system at SourceForge (follow `bugs' link on http://sourceforge.net/projects/libmss).
However, if the bug is very minor or you're too lazy, then simply drop a line to libmss-devel@lists.sourceforge.net.
In development:
Released on October 2001:
<no_mss.h>
.
NULL
without
generating a warning, because it is legal with latest C and C++
standards.
Released on November 1998:
Released on April 1998:
MSS_PTR_SIZE_T
and MSS_PRINTF_SIZE_T
were
added).
MSS_LOG_BLOCK_LIST_FILTERED
, thanks
to Olaf Stoyke for contributing with this function.
Released on February 1998:
config.h
, and added support for run-time
configuration files.
new[]
, delete[]
, xmalloc()
,
xrealloc()
, xfree()
, cfree()
and strdup()
.
MSS_SET_BLOCK_LABEL()
MSS_DUMP_BLOCK()
January 1998: (never released)
use_mss.h
file, and put everything in
mss.h
.
SIGSEGV
sometimes when writing
the logfile to a file. (How did this go by unnoticed anyway by the
way).
check_if_initialized()
.
January 1998: (never released)
realloc()
and calloc()
.
MALLOC_FAIL_PERCENTAGE
.
CHECK_ALL_ON_MALLOC
.
MSS_DISABLE_THREADING
and
MSS_ENABLE_THREADING
to make MSS thread-safe.
free()
memory which was allocated by new
and vice versa.
MSS_WORD_WRAP_LOG_FILE
.
MSS_ENTER_SCOPE
, MSS_LEAVE_SCOPE
-Wall -W -ansi -pedantic
on GCC
anyway :)
CHECK_CONSTANT_BLOCK
command, since this is
now covered by MSS_LOG_CHECK_BLOCK_AT()
.
mss.h
to config.h
, to avoid
any name-conflicts with the user's program. Now everything in
mss.h
and use_mss.h
starts with MSS_
or
mss_
.
December 1997: (never released)
malloc()
and free()
added, as
MSS was rewritten in C by Peter.
main()
not being
detected by MSS was fixed.
stdout
or a user
selectable logfile.
MSS_
prefix to all global functions in
mss.c
and cppspec.cc
, and also the #defines
in
use_mss.h
.
November 1997:
NULL
pointer. Thanks to Przemyslaw G. Gawronski for reporting
this bug.
October 1997:
FINISH_MEM
feature.
September 1997:
NULL
pointer deallocation
(Thanks to Miguel Murillo :)
CHECK_POINTER
, LOG_MSG
.
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.
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.
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.
In 2000 Laurynas Biveinis has found an incompatibility between MSS version 1.2 and GNU C++ compiler version 2.95 and set a workaround to Peter. But Peter replied that he would hand over maintenance of MSS if somebody comes up. In 2001, Laurynas has made a few bugfixes to MSS and wanted to publish them. However, this time both authors didn't reply to any mails, so Laurynas just went on and uploaded version 1.2.1 to SimtelNet.
MSS_CHECK_ALL_BLOCKS
: Reference
MSS_CHECK_BLOCK_AT
: Reference
MSS_CHECK_POINTER_VALIDITY
: Reference
MSS_CURRENTLY_USED_MEM
: Reference
MSS_DISABLE_LOG_OUTPUT
: Reference
MSS_DUMP_BLOCK
: Reference
MSS_ENABLE_LOG_OUTPUT
: Reference
MSS_ENTER_SCOPE
: Reference
MSS_LEAVE_SCOPE
: Reference
MSS_LOG_BLOCK_LIST
: Reference
MSS_LOG_BLOCK_LIST_FILTERED
: Reference
MSS_LOG_INFO
: Reference
MSS_LOG_INTERNAL_INFO
: Reference
MSS_LOG_MSG
: Reference
MSS_MAXIMUM_USED_MEM
: Reference
MSS_NUMBER_OF_ALLOCATED_BLOCKS
: Reference
MSS_REGISTER_CONSTANT_BLOCK
: Reference
MSS_SET_BLOCK_LABEL
: Reference
MSS_STARTUP
: Reference
MSS_UNREGISTER_CONSTANT_BLOCK
: Reference
Version 2, June 1991
Copyright © 1989, 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification follow.
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.
In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
one line to give the program's name and a brief idea of what it does. Copyright (C) yyyy name of author 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.
The hypothetical commands show w
and show c
should show
the appropriate parts of the General Public License. Of course, the
commands you use may be called something other than show w
and
show c
; they could even be mouse-clicks or menu items--whatever
suits your program.
You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice
This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.