home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
CPROG
/
LABYTE.ZIP
/
LABYTE.DOC
< prev
next >
Wrap
Text File
|
1992-05-08
|
18KB
|
433 lines
Memory Manager
Version S1.1
One of the most difficult parts of programming in C is handling
memory and its pointers. At least, that is what I found. To help me
reduce these problems, I wrote LAByte.
The functions provided are:
1. Handling the allocation of memory blocks, freeing the blocks,
checking for memory corruption.
2. Provide a method of tracing the entrance into each function.
NOTE: There are two separate traces maintained by the module. The
first is for the memory functions and the second is for
function tracing.
Memory Processor Functions
All calls are "traced". If an error occurs the trace table is written
to a file named LATrace.LAC. Each of the function calls use the file
name and line number. You may supply your own file name as a
character pointer or use the __FILE__ symbol, likewise, you may use
__LINE__ symbol for the line number. More on the trace later.
Allocation of Memory
Memory is allocated from the far heap. A far character pointer is
returned pointing to the first usable byte of the block. The block
is initialized to NULLs.
prototype:
char far *mem_getmain(char *File, int Line, char Fun1, char Fun2, int Size);
char *File = A name that will point you to the module doing the
getmain. You may use the __FILE__ symbol.
int Line = A number representing the place in the module where the
getmain was called. You may use the __LINE__ symbol.
char Fun1 = These characters can be set to anything that will help
char Fun2 point you in the right direction. I use the selection
characters from the main menu and its pull down menu.
int Size = The size of the memory block to be allocated.
example:
int Samp_Fun()
{
char far *Cnfg;
Cnfg = mem_getmain(__FILE__, __LINE__, 'M', 'C', sizeof(CONFIG_DATA));
}
Freeing A Memory Block
When called, freemain will verify the integrity of the block
passed, abending if it is not valid or freeing the block and
returning to the calling return. This function can only be
used to free memory blocks allocated by the getmain function
because of the trace chain and block integrity header and
trailer.
prototype:
int mem_freemain(char *File, int Line, char far *Pointer);
char *File = A name that will point you to the module doing the
getmain. You may use the __FILE__ symbol.
int Line = A number representing the place in the module where the
getmain was called. You may use the __LINE__ symbol.
char far *Pointer = The pointer returned from the call to getmain.
example:
int Samp_Fun()
{
char far *Cnfg;
mem_freemain(__FILE__, __LINE__, Cnfg);
}
Freeing Memory Blocks By A Function
When called, cleanup will verify the integrity of all blocks
on the chain where the passed function matches the char passed in
Fun1 of the getmain, abending if an invalid is encountered or
freeing the block and returning to the calling return. The reason
for using cleanup is to eliminate the build up of unreleased memory
as a function ends or as a quick and easy way to release all memory
that was allocated to accomplish the function.
prototype:
int mem_cleanup(char *File, int Line, char Fun);
char *File = A name that will point you to the module doing the
getmain. You may use the __FILE__ symbol.
int Line = A number representing the place in the module where the
getmain was called. You may use the __LINE__ symbol.
char Fun = The character passed in Fun1 of the getmain for the
blocks to be released.
example:
int Samp_Fun()
{
mem_cleanup(__FILE__, __LINE__, 'M');
}
Freeing All Memory Blocks
When called, freeall will verify the integrity of all blocks
on the chain, abending if invalid or freeing the blocks and
returning to the calling return.
prototype:
int mem_freeall(char *File, int Line);
char *File = A name that will point you to the module doing the
getmain. You may use the __FILE__ symbol.
int Line = A number representing the place in the module where the
getmain was called. You may use the __LINE__ symbol.
example:
int Samp_Fun()
{
mem_freeall(__FILE__, __LINE__);
}
Memory Trace Entry
Internal table
Memory trace entries are allocated from the near heap as
memory is allocated and added to the chain. The first trace
entry address is saved in the anchor in LAByte.C named
MemAnchor.
typedef struct {
int MemOK; /* Normally NULL but set to a value
if an error is detected. see
Error Codes below */
char MemMod[15]; /* File Name from getmain */
int MemLine; /* Line Number from getmain */
char MemFun; /* Fun1 from getmain */
char MemUse; /* Fun2 from getmain */
int MemLen; /* Length from getmain */
void far *MemAddr; /* Address of the memory block */
void *MemPrev; /* Address of the previous memory trace
entry or the memory anchor in the
header */
void *MemNext; /* Address of the next memory trace
entry or null if this is the last
entry on the chain */
} MEMTBL;
LATrace.Lac File Entry (see Cancelling The Program below)
M---5D8D:0004---0---main.c---25---M---C---365---5D75:0008---6C60:0004---0000:0000
^-A ^-B ^-C ^-D ^-E ^-F ^-G ^-H ^-I ^-J ^-K
A) Indicator showing this as a memory trace entry
B) Address of this trace entry
C) Error Code, see Error Codes below
D) File Name
E) Line Number
F) Fun1
G) Fun2
H) Length of the memory block
I) Address of the memory block
J) Address of previous memory trace entry
K) Address of next memory trace entry
Error codes
mem_freemain function
1 - There is no memory on the trace chain
2 - Can't find find the memory block on the chain
3 - The backward chain has been corrupted
4 - The forward chain has been corrupted
5 - The header of the memory block has been corrupted
6 - The trailer of the memory block has been corrupted
mem_cleanup function
11 - The backward chain has been corrupted
12 - The header of a memory block has been corrupted
13 - The trailer of a memory block has been corrupted
mem_freeall function
21 - The backward chain has been corrupted
22 - The header of a memory block has been corrupted
23 - The trailer of a memory block has been corrupted
If the trailer of a memory block has been corrupted,
error codes 6, 13 and 23, probably the definition of the area
is larger than the memory block allocated.
If the header is corrupted, error codes 5, 12 and 22,
either the pointer has been changed, an array was
improperly indexed or the previous area was overrun.
For all other error codes, the memory trace chain has
been corrupted in some fashion. Since the chain is
allocated from the near heap, it should not be effected
by your program. The problem could be caused If a pointer
gets incorrectly set, if your program allocates areas from the
near heap and corrupts it, or a program bug in LAByte.
Function Tracing Functions
Function tracing is an optional facility provided to determine the
logic path through your program. Entries are placed in the trace
table by calling function trace_entry. The trace table is anchored
to the TraceTbl pointer in LAByte.C. The table, by default, is
large enough to hold the last 100 entries. The size of the table
can be changed by changing the define TRACEELEMS in the header.
Because of performance, the trace table is held in memory until the
program calls cancel_program. Cancel_program will be called if the
memory processor functions detect an error or by your program. The
trace table can be used during testing if a debugger is not the
best answer to a particular problem. Also the trace can be left
active in the production version of your program and your customer
can upload the LATrace.Lac file to help you determine what occurred
if your program should fail.
I have NOT noticed any measurable performance impact by using this
trace but some impact may be noticiable if it is called too often.
But this should only be important in the production version of your
program. If you need to create a "lot" of trace entries to
debug a problem, the size of the trace table should be increased.
Activating/Deactivating The Trace
The trace logic can be activated or deactivated by the presence or
absence of a define for LATRACE in LAByte.C. If present, the trace
logic will be active. If LATRACE is absent, the trace table will
not be allocated and calls to trace_entry will simply issue a return.
Placing An Entry In The Trace Table
I normally place a call to trace_entry as the first function of
each of my functions and denote it with a type of E. Additional
entries can be made to pinpoint problems or provide critical
information if problems occur.
prototype:
void trace_entry(char Type, char *File, int Line)
char Type = A character indicating the type of entry being made.
char *File = A name that will point you to the module doing the
getmain. You may use the __FILE__ symbol.
int Line = A number representing the place in the module where the
getmain was called. You may use the __LINE__ symbol.
example:
int Samp_Fun()
{
trace_entry('E', __FILE__, __LINE__); /* Trace Entry to Paragraph */
}
Cancelling The Program And Dumping The Trace Table To A File
This function is used to write both the memory trace table and the
function trace table to LATrace.Lac. Even if the trace logic is
disabled, the memory trace is written. This function does NOT
return.
There is a sample of LATrace.Lac provided.
prototype:
void cancel_prog(int ExitCode)
int ExitCode = The code that is used to exit() the program after
the trace table is written.
example:
int Samp_Fun()
{
cancel_prog(4);
}
Function Trace Entry
Internal table
Function trace entries are held in the TraceTbl as defined in
the LAByte.C file. Room is provided for 100 entries by
default but can be changed by changing the value of the
TRACEELEMS define.
#define TRACEELEMS 100 /* Size of trace table */
typedef struct
{
char Wrap; /* Indicates if table is wrapping */
int TracePtr; /* Pointer to the current entry */
struct
{
char Type; /* Type from trace_entry */
char Mod[15]; /* File from trace_entry */
int Line; /* Line from trace_entry */
} TraceElem[TRACEELEMS];
} TRACETBL;
TRACETBL *TraceTbl = NULL;
LATrace.Lac File Entry
T---E---main.c---21
^-A ^-B ^-C ^-D
A) Indicator showing this as a function trace entry
B) Type of trace_entry
C) File of trace_entry
D) Line of trace_entry
Including In Your Program
Place LAByte in the directory containing the other modules of your
program. Include the module in your .Mak file or project file for
the IDE. Change your program to call the routines and recompile
the program. The LAByte header need only be included in LAByte.C.
EXAMPLES OF USE
1. Storage overlay
int stg_overlay()
{
char far *BadFld;
BadFld = mem_getmain(__FILE__, _LINE__, '1', '2', 20);
memset(BadFld, ' ', 30);
}
As a result of the memset, 10 bytes after the area allocated by the
getmain are set to blanks. Depending on the use of these bytes the
program could abort immediately, destroy data or function without
any indication of the bug. The worse possible situation to occur
is the last because the program may start abending after future
changes are made and it will be almost impossible to relate the
problem to the actual changes made. At least with the first two
cases you are more apt to realize that a problem exists and take
steps to correct it.
When a free function is called, the corruption will be detected and
the memory trace written to LATrace.Lac in the current directory.
From the memory trace, the bad area can be determined an you will
know where the area was allocated. From the function trace, you
can determine the logic path that lead to the problem.
2. Program loop
Finding a loop, which is why, in most cases, the system "locks up",
can take a significant amount of time depending on the size and
complexity of the logic. A good debugger helps. By including the
trace_entry as the first function call of each function, to find a
loop would look like this:
Start the program executing under the debugger.
When the program loops, break the code.
Find the trace table in LAByte.
Find the current entry.
Scan backward to find the functions particpating in the loop.
This will help you determine where to put the breakpoints in
the debugger.
LAByte is Shareware
These routines are supplied on an as-is basis. We attempt to
insure the accuracy of all our products. We do warrant that our
software will not cause corruption of the information contained on the
disk containing this product with the exception of that caused by
hardware failures and that caused by a virus. We gaurantee that the
software is virus free when uploaded to the original BBS but we cannot
prevent its infection beyond that point. Because this module is
provided as source code and not in executable form, it is unlikely to
be infected. To avoid problems with viruses, we recommend that you use
a good virus scanning product on this product and ALL software
downloaded from a BBS. If you detect such a virus, we would like to
know about it as soon as possible.
The routines are written in Borland C++ from Borland International.
The code is not object-oriented.
You may freely copy and share this program as long as the routines
and documentation are copied in their entirity.
These routines are provided as a shareware product. You may use it
without registering it for a reasonable time. The routines may not be
included in any product, except for your own personal use, without
registering it. If you should decide to register it, we will send you
any corrections that may come to our attention. In addition, you will
be made aware other products from the Programming Support Division of
Logical Answers Corp as they become available.
Registration Form:
Name: _____________________________________________
Company: __________________________________________
Street: ___________________________________________
___________________________________________
City: __________________ State: ____ Zip: _______
Product: PS01 Serial #: S1A0001
Where did you get your copy of this product?
_________________________________________________
Do you want to be added to our mailing list? ______
Registration Fee: 15.00
Pa. Tax (6%): ______
Send your registration to:
Logical Answers Corp.
Programming Support Division
P. O. Box 33
Brownstown, PA 17508
(717) 627-4181