166 lines
5.2 KiB
C
166 lines
5.2 KiB
C
|
|
||
|
#ifndef Smem_includeD
|
||
|
#define Smem_includeD
|
||
|
|
||
|
|
||
|
/* compile time adjustable parameters : */
|
||
|
|
||
|
/* if not defined, flat malloc() and free() is used */
|
||
|
#define Smem_own_functionS
|
||
|
#ifdef Smem_no_own_functionS
|
||
|
#undef Smem_own_functionS
|
||
|
#endif /* Smem_no_own_functionS */
|
||
|
|
||
|
/* if not defined, the record items will be smaller by 8 byte
|
||
|
but deletion of items may be much slower */
|
||
|
#define Smem_with_hasH
|
||
|
|
||
|
|
||
|
|
||
|
struct SmemiteM {
|
||
|
|
||
|
char *data;
|
||
|
size_t size;
|
||
|
|
||
|
struct SmemiteM *prev,*next;
|
||
|
|
||
|
struct SmemiteM *hash_prev,*hash_next;
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef Smem_own_functionS
|
||
|
|
||
|
char *Smem_malloc();
|
||
|
int Smem_free();
|
||
|
|
||
|
#define TSOB_FELD(typ,anz) (typ *) Smem_malloc((anz)*sizeof(typ));
|
||
|
#define Smem_malloC Smem_malloc
|
||
|
#define Smem_freE Smem_free
|
||
|
|
||
|
#else /* Smem_own_functionS */
|
||
|
|
||
|
#define TSOB_FELD(typ,anz) (typ *) malloc((anz)*sizeof(typ));
|
||
|
#define Smem_malloC malloc
|
||
|
#define Smem_freE free
|
||
|
|
||
|
#endif /* ! Smem_own_functionS */
|
||
|
|
||
|
int Smem_set_record_items();
|
||
|
int Smem_stderr();
|
||
|
int Smem_clone_string();
|
||
|
|
||
|
|
||
|
#define Smem_hashsizE 251
|
||
|
#define Smem_hashshifT 8
|
||
|
|
||
|
#ifdef Smem_included_by_smem_C
|
||
|
|
||
|
double Smem_malloc_counT= 0.0;
|
||
|
double Smem_free_counT= 0.0;
|
||
|
double Smem_pending_counT= 0.0;
|
||
|
struct SmemiteM *Smem_start_iteM= NULL;
|
||
|
struct SmemiteM *Smem_hasH[Smem_hashsizE];
|
||
|
double Smem_hash_counteR[Smem_hashsizE];
|
||
|
|
||
|
/* these both init values are essential, since setting Smem_record_itemS=1
|
||
|
by use of Smem_set_record_items() initializes the hash array
|
||
|
(i do not really trust the compiler producers to have read K&R) */
|
||
|
int Smem_hash_initializeD= 0;
|
||
|
int Smem_record_itemS= 0;
|
||
|
|
||
|
double Smem_record_counT= 0.0;
|
||
|
double Smem_record_byteS= 0.0;
|
||
|
|
||
|
#else /* Smem_included_by_smem_C */
|
||
|
|
||
|
extern double Smem_malloc_counT;
|
||
|
extern double Smem_free_counT;
|
||
|
extern double Smem_pending_counT;
|
||
|
extern struct SmemiteM *Smem_start_iteM;
|
||
|
extern struct SmemiteM *Smem_hasH[Smem_hashsizE];
|
||
|
extern double Smem_hash_counteR[Smem_hashsizE];
|
||
|
extern int Smem_hash_initializeD;
|
||
|
extern int Smem_record_itemS;
|
||
|
extern double Smem_record_counT;
|
||
|
extern double Smem_record_byteS;
|
||
|
|
||
|
#endif /* ! Smem_included_by_smem_C */
|
||
|
|
||
|
|
||
|
|
||
|
#endif /* ! Smem_includeD */
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
smem
|
||
|
|
||
|
Functions to replace malloc() and free() in order to get more control
|
||
|
over memory leaks or spurious errors caused by faulty usage of malloc()
|
||
|
and free().
|
||
|
|
||
|
|
||
|
Sourcecode provisions:
|
||
|
|
||
|
Use only the following macros for memory management:
|
||
|
TSOB_FELD(type,count) creates an array of items of given type
|
||
|
Smem_malloC() analogue of malloc()
|
||
|
Smem_freE() analogue of free()
|
||
|
One may #define malloc Smem_malloC resp. #define free Smem_freE
|
||
|
but better would be to review (and often to streamline) the sourcecode
|
||
|
in respect to those two functions.
|
||
|
|
||
|
|
||
|
Speed versus control:
|
||
|
|
||
|
In production versions, where maximum speed is required, one may undefine
|
||
|
the macro Smem_own_functionS in smem.h .
|
||
|
This causes the above macros to directly invoke malloc() and free() without
|
||
|
any speed reduction (and without any additional use).
|
||
|
Undefinitio can be done globaly by modifying smem.h or locally by defining
|
||
|
Smem_no_own_functionS before including smem.h .
|
||
|
|
||
|
If Smem_own_functionS remains defined, then the functions
|
||
|
Smem_malloc()
|
||
|
Smem_free()
|
||
|
are used rather than malloc() and free().
|
||
|
They count the number of calls to maintain a rough overview of memory usage.
|
||
|
Smem_malloc() additionally checks for 0 size and Smem_free() checks for
|
||
|
NULL pointers, which they both report to stderr. Eventually one should set
|
||
|
a breakpoint in function Smem_protest() to learn about the origin of such
|
||
|
messages.
|
||
|
A status line may be obtained by Smem_report() or printed by Smem_stderr().
|
||
|
|
||
|
As long as the variable Smem_record_itemS is set to 0, there is not very much
|
||
|
overhead compared with malloc() and free().
|
||
|
If the variable is set to 1 by Smem_set_record_items() then all malloc()
|
||
|
results are kept in a list where they will be deleted by their corresponding
|
||
|
Smem_free() calls. If a pointer is to be freed, which is not recorded in the
|
||
|
list then an error message will be printed to stderr. The memory will not
|
||
|
be freed !
|
||
|
This mode not only may be very slow, it also consumes at least 16 byte per
|
||
|
piece of data which was obtained by malloc as long as it has not been freed.
|
||
|
Due to the current nature of the list, large numbers of memory items are freed
|
||
|
much faster in the reverse order of their creation. If there is a list of
|
||
|
100000 strings to delete, it is very rewarding to free the youngest ones first.
|
||
|
A shortcut via hashing is available but consumes 24 bytes rather than 16.
|
||
|
(see above Smem_with_hasH )
|
||
|
|
||
|
The function Smem_is_recorded() can be used to check wether a pointer is
|
||
|
valid according to the list. It returns :
|
||
|
0 = is not in list , 1 = is in list , 2 = recording is off
|
||
|
|
||
|
If one decides to start recording malloc() results in the midst of a program
|
||
|
run, one has to be aware of false protests of Smem_free() if a memory piece
|
||
|
has been allocated before recording started. This will also cause those pieces
|
||
|
to be memory leaks because Smem_free() refuses to delete them. (Freeing memory
|
||
|
that was not obtained by malloc or was already freed previously can result in
|
||
|
deferred SIGSEGV or similar trouble, depending on OS and library.)
|
||
|
Also in that case one should stop recording before ending the program, to
|
||
|
avoid a lot of false complaints about longliving memory objects.
|
||
|
|
||
|
*/
|