home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / biblioteki / c_library / apurify / doc / mit-apurify.doc < prev    next >
Text File  |  1977-12-31  |  26KB  |  607 lines

  1.                    MIT-APurify v1.3
  2.                    ----------------
  3.  
  4.                MIT-syntax version (GCC).
  5.  
  6.                 (c) by Samuel DEVULDER
  7.                    jan. 1996
  8.  
  9.                Samuel.Devulder@info.unicaen.fr
  10.  
  11. DESCRIPTION (SHORT):
  12. --------------------
  13.     This is APurify for compilers with MIT syntax asm-files. As  far  as  I
  14.     know only GCC uses such a syntax. So that version is indeed  a  version
  15.     for the GCC compiler. If you are using an  other  compiler,  then  read
  16.     MOT-APurify instead. In the following of that document, APurify  stands
  17.     for MIT-APurify, and I assume you're using the GCC compiler.
  18.  
  19.     APurify is a program that allows you to detect bad accesses  to  memory
  20.     of your programs without any kind of specific external  devices  (MMU).
  21.     It avoids bugs due to accessing memory not owned by your program.
  22.  
  23. INSTALLATION:
  24. ------------
  25.     That archive contains the version of APurify for the  GCC  compiler
  26.     as well for other compilers. Here is a description of gcc-related files
  27.     of this archive for that version. It also gives you  what  to  do  with
  28.     those files to make an installation.
  29.  
  30.     - doc/MIT-APurify.doc    The file you are currently  reading. Put it
  31.                 with all your doc files. It is usefull from
  32.                 time to time.
  33.  
  34.     - doc/History        The whole history.  (this  file is not very
  35.                 usefull for common people). Do whatever you
  36.                 want with it.
  37.  
  38.     - bin/MIT-APurify    The parser tuned for the MIT syntax. Rename
  39.                 it as APurify and put it someware  in  your
  40.                 path.
  41.  
  42.     - lib/APur-gcc.a    The link-time library.    Rename it as APur.a
  43.                 and  put  it  someware    in   your   library
  44.                 search-path.
  45.  
  46.     - test/test.c        Source of a stupid test file.  Just here to
  47.                 let  you  remake  the  test   program.     Do
  48.                 whatever you want with it.
  49.  
  50.     - test/test.gcc     Test file  Apurify'ed.  Run it  to  see how
  51.                 APurify is useful :-).
  52.  
  53.  
  54. SYNOPSIS:
  55. --------
  56.     Usage: APurify [-revinfo] <inputfile> [options]
  57.  
  58.     Where options can be:
  59.  
  60.     ?     To display this usage
  61.     -h     To display this usage
  62.     -?     To display this usage
  63.     -tb     To test memory referenced through base register
  64.     -ts     To test memory referenced through stack register
  65.     -tl     To test memory referenced through local stack frame
  66.     -tp     To test pea instructions
  67.     -o arg     Specifies output file (def=%s)
  68.     -br arg  Sets the base register (def=A4)
  69.     -mp arg  Sets the main entry-point (def=_main)
  70.  
  71.     Options can be anywhere on the command line. NOTE: They can  nomore  be
  72.     merged together, they must be separated by a space. You  can pre-define
  73.     them with the environment variable AP_MITP_OPT. For example, if you do:
  74.  
  75.     CLI> SetEnv AP_MITP_OPT "-tb -br A5"
  76.  
  77.     Then, when "-tb -br A5" will automatically  be  added  to  the  command
  78.     line. The space between an option and its argument can be ommited. Thus
  79.     "-br A4" is the same as "-brA4". Here is a description of arguments and
  80.     flags:
  81.  
  82.     -revinfo    This displays informations  about APurify  (name,  size and
  83.         date of modules and number of  compilation  done  for  that
  84.         version).
  85.  
  86.     -br arg    This  sets  the  base  register  used  to  reference memory
  87.         in SMALL_DATA model. Usually A4 is used  for  that  perpose
  88.         and that's the default. If A5  is  used  instead  then  add
  89.         -brA5 on your command line.
  90.  
  91.     -tb     This enable APurify to check all referenced  memory through
  92.         the base register (see -br). If you are using a  SMALL_DATA
  93.         model, add this flag on  your  command    line.  By  default,
  94.         APurify won't check  memory  referenced  through  the  base
  95.         register.
  96.  
  97.         NOTE: for safest check, you should always use that  option,
  98.         even if you're not in smalldata model (A4 may  be  used  as
  99.         a temporary register in that case). To allow this, you    can
  100.         use the environment variable.
  101.  
  102.     -ts     This  enable  APurify to  check memory referenced  by stack
  103.         pointer (SP or A7). By default  APurify  won't  check  such
  104.         memory accesses (to reduce the code size and  increase  the
  105.         runtime speed). That option will detect when  you  have  no
  106.         more room on your stack (stack overflow).
  107.  
  108.     -tl     This enable APurify to check  memory  referenced   by local
  109.         stack pointer (the one that is link'ed and  unlink'ed  when
  110.         enterring and exiting a C-function). By  default,  this  is
  111.         switch off. This  option  allow  APurify  to  detect  stack
  112.         overflow.
  113.  
  114.     -tp     This enable APurify to check indirect  adresses pushed onto
  115.         the stack by using a pea. By  default  this  is  off.  When
  116.         used, that option will check things like "pea  a2@(10)"  or
  117.         the like. This can help  you  with  memory  accessed  by  a
  118.         pointer in a code that has not been APurify'ed. For example
  119.         this is usefull  for  things  like  fread(&ptr[10],10,1,fp)
  120.         because in that case the "pea a2@(10)" used to push on  the
  121.         stack &ptr[10] will be checked and if ptr[10] is not  owned
  122.         by your program, you'll get an APurify error.  Please  note
  123.         that this may no work all the time  since  &ptr[0]  can  be
  124.         translated as "movel a0,sp@-" which  won't be checked.
  125.  
  126.     -o arg    This specifies the name of the outputfile. If  ommited    the
  127.         outputfile will be the same as the inputfile (source file).
  128.         The name of the output file can be defined by a  real  name
  129.         or a pattern. A pattern is a string where special sequences
  130.         of characters (called specifier) are  replaced  by  special
  131.         strings. Let's suppose that inputfile is equal to
  132.  
  133.                 drive:path/file.ext
  134.  
  135.         Here is a description of specifiers:
  136.  
  137.             %s    will be replaced by the full source name:
  138.  
  139.                 drive:path/file.ext
  140.  
  141.             %S    will expand to the  full  source name  without    the
  142.             extension:
  143.  
  144.                 drive:path/file
  145.  
  146.             %b    stands for the full basename:
  147.  
  148.                 file.ext
  149.  
  150.             %B    is a shortcut for the  full  basename  without    the
  151.             extension:
  152.  
  153.                 file
  154.  
  155.             %p    is the path (ending "/" or ":" is included):
  156.  
  157.                 drive:path/
  158.  
  159.             %e    is the extension ("." is ommited):
  160.  
  161.                 ext
  162.  
  163.         Thus, if you put "-o ram:%B-apurify.%e" in the commandline,
  164.         then the outputfile  will  be  "ram:file-apurify.ext"  with
  165.         our example.
  166.  
  167.     -mp arg    This tells APurify which label should be considered as    the
  168.         entry-point. By default it is set to "_main", and it should
  169.         not be modified.
  170.  
  171.     -?
  172.     -h
  173.     ?        Obvious options.
  174.  
  175.  
  176. DESCRIPTION (A BIT LONGER):
  177. --------------------------
  178.     As a general rule, at the microprocessor level, there is  two  kind
  179.     of ways to access memory. There is direct access and indirect access to
  180.     memory. For example, in C, direct access can be viewed as accessing  to
  181.     global variables. Indirect access corresponds  to  accessing  an  array
  182.     value. More precisely, direct access corresponds to reading or  writing
  183.     a variable whose address is known at compilation  time  (or  since  the
  184.     loading of the program into the memory). Indirect access  is  used    for
  185.     variables whose adress is dynamicaly determined  by  the  program.    For
  186.     example, if p is a pointer to an array allocated by malloc(), *p is  an
  187.     indirect access. Such an access occur also in case of instruction  like
  188.     T[i] where T is a global array, because the  address  of  T[i]  is    not
  189.     known at compilation time, since it depends on the index value i. Using
  190.     indirect access to memory is called indirection.
  191.  
  192.     A regular program must not access memory not owned by it. That kind
  193.     of access can be qualified as illegal.
  194.  
  195.     Illegal direct access  to   memory  is    not  possible, because     by
  196.     definition, only global  variables can be  accessed that  way and those
  197.     variables belongs obviously to the program    (except for code written in
  198.     assembly   language   that    references  absolute   values, for example:
  199.     "btst  #6,$bfe001"; but that  kind of  code  is not a  good programming
  200.     :-)). So we can assume that direct access to memory is always right.
  201.  
  202.     On the other hand,  it is sure    that indirect access to  memory can
  203.     be illegal.  Many bugs are made by    overstepping array  boundaries.  If
  204.     that oversteppings are  in reading a value, there  is not much  trouble
  205.     for over running tasks (it is an error inside your  task); but if it is
  206.     in writing you may directly interfere with other tasks and big mess can
  207.     happen (total breakdown of the system).
  208.  
  209.     APurify works on  that kind of access  by verifying the validity of
  210.     indirect access to memory. It remebers the memory that was allocated by
  211.     the program and check the integrity of  each access. One can think that
  212.     makes a lot of tests ! Well, yes, but APurify is  not  designed  to  be
  213.     used in the general use of programs; just  in  test  phases.  Moreover,
  214.     indirections  do  no  occur  very  often  actually.  Only    array-based
  215.     variables produces indirections.  Thus,  the  variables  on  the  stack
  216.     --although being accessed by  indirection--  are  not  checked  because
  217.     their access is always safe (at least if there is no stack overflow !).
  218.     Also, in SMALL_DATA model, global  variables  access  is  done  through
  219.     indirection, but they are not checked.
  220.  
  221.     If an illegal access is found, APurify displays an error message on
  222.     the error stream of the program  by  default.  There  is  two  kind  of
  223.     illegal accesses. Some are accesses to memory that    doesn't  belong  to
  224.     the program (it is called an access between blocks),  some  others  are
  225.     accesses to a part of memory owned by a program and an other  part    not
  226.     owned by it (it is an overstepping  of  a  block).  You  can  see  this
  227.     visually: If [ 1 ] and [ 2 ] represent  two  blocks  allocated  by    the
  228.     program and ( 3 ) the memory accessed, then
  229.  
  230.          ---- [ 1 ] ---- ( 3 ) ---- [ 2 ] ---->
  231.         0                       increasing address
  232.  
  233.     corresponds to the first kind of illegal access and
  234.  
  235.              ---- [ 1 ( ] 3 ) ---- [ 2 ] ----->
  236.     or
  237.              ---- [ 1 ] ---- ( 3 [ ) 2 ] ----->
  238.  
  239.     corresonds to the second kind of access. The first kind is very  common
  240.     but the second is quite rare (it's rather a misaligment problem).
  241.  
  242.     APurify has two output modes. One is verbose an tries to  give    lot
  243.     of informations by using words. The other one is more brief  and  gives
  244.     you the same informations but you'll have to decode them.
  245.  
  246.     When APurify starts and ends, it outputs  the  date/time.  This  is
  247.     useful if you are using logfiles. With that, you can keep all your logs
  248.     in a  single  file    and  retrieve  any  execution  with  it's  date  of
  249.     execution.
  250.  
  251.     In case of an error, APurify displays some  text.  The    first  line
  252.     looks like this one:
  253.  
  254.     **** APURIFY ERROR ! [$<N1>(<N2>) <ATTR> (<TEXT1>)] <TEXT2>:
  255.  
  256.     That line represent  the  accessed    memory.  <N1>  is  the    hexadecimal
  257.     address accessed. <N2> is the length of the access (in decimal). <ATTR>
  258.     represents the type of acess. <TEXT1> allows you to find where in  your
  259.     code the illegal accessed had happened. <TEXT2> describe  the  kind  of
  260.     illegal access.
  261.  
  262.     If the length (<N1>) is 1, then it was a byte access. 2 stands  for
  263.     a short access,  4    for  a    int/long  and  >4  for    movem  instruction.
  264.     Attributes, <ATTR>, can be "R--" or "-W-". The first one represents  an
  265.     access in reading a value and the second an access in writing a value.
  266.  
  267.     The text <TEXT1> look like this:
  268.  
  269.         <NAME>, PC=$<PC#> HUNK=$<HUNK#> OFFSET=$<OFF#>
  270.  
  271.     <NAME> is the name of the subroutine where the  error  occured.  It  is
  272.     always displayed (even if it is a "static" one). The rest of  the  line
  273.     can be partially displayed, showing as much informations as APurify can
  274.     get. <PC#> is a hexadecimal address pointing to  the  instruction  that
  275.     produced the error. <HUNK#> and <OFF#> are    the  hunk  number  and    the
  276.     relative offset of <PC#>. Using <HUNK#> and <OFF#> and a  disassembler,
  277.     you can very easilly find where your code is bad (BTW, I use dobj  from
  278.     netdcc, (c) by Matt Dillon). Please note  that  in  this  new  version,
  279.     <PC#> will nomore point to some instruction before the faultly one.  It
  280.     is always the real faultly adress.
  281.  
  282.     The remaining lines show the context  of  the  illegal    access.  It
  283.     gives you informations about the  surronding  memory  blocks  owned  by
  284.     your program. Each    block  is  displayed  according  to  the  following
  285.     pattern:
  286.  
  287.                [$<N1>(<N2>) <ATTR> (<TEXT>)]
  288.  
  289.     where <N1> is the hexadecimal address of the beginning  of    the  block,
  290.     <N2> its length (in decimal). Note that  the  length  may  seem  to  be
  291.     longer than the one allocated by malloc() and  the  address  may  point
  292.     before the one you obtained via malloc(). This is not wrong !  In  fact
  293.     you must know that the malloc() subroutine may  add  some  informations
  294.     (like an double-chained list or the length of the  allocation)  to  the
  295.     block you've requested. Those extra informations  are  put  before  the
  296.     address you recieve. That explain this behavior.  In  this    version  of
  297.     APur.lib, this takes 12 ($C) extra bytes. So if you allocate 10  bytes,
  298.     don't be suprised if APurify thinks you've requested 22 bytes.
  299.  
  300.     <ATTR> are 3 status characters RWS
  301.  
  302.     where R means: read-enable block
  303.           W means: write-enable block
  304.           S means: system block (block not controlled by the program).
  305.  
  306.     If one access is forbidden, the letter '-' replaces  the  corresponding
  307.     character. <TEXT> is actually  the    name  of  the  procedure  that    has
  308.     allocated the block.
  309.  
  310.     With each block you can find an offset. That offset is the distance
  311.     between that block and the faultly address. In verbose  mode,  you    can
  312.     see some text explaining things about the relative position of a  block
  313.     and the accessed memory. In non-verbose  mode  you    can  just  see    the
  314.     offsets followed by the blocks. The shorter offset is  displayed  first
  315.     since that block is the one that is more likely overstepped.
  316.  
  317.     When an illegal writing occur (the only dangerous thing you can  do
  318.     by indirection, indeed), a requester opens to tell you about that. With
  319.     that requester, you can stop your program to prevent the  deadly  error
  320.     to really happen. If you wish  so,    exit()  is  called.  You  can  also
  321.     ignore that error or ignore all such errors  (but  then  you'll  surely
  322.     meet the guru !).
  323.  
  324.     APurify checks the memory allocated but not freed by  the  program.
  325.     (in fact, it detects non deallocated-blocks on library-closing time).
  326.  
  327.     It  knows  about  memory  location  independant  of   the   program
  328.     execution. That is to say, the first kilobyte of memory  that  contains
  329.     interrupt vectors of the 680x0 processor, the program segments and    the
  330.     stack. Accessing to those blocks  will  be    illegal.  They    got  the  S
  331.     attribute (for SYSTEM blocks).
  332.  
  333.     It takes into  account    memory    block  allocated  by  malloc()  and
  334.     AllocMem(), and indirect allocated block (by OpenScreen() for example).
  335.     But I did not test the last kind of allocation. Anyway,  it  should  be
  336.     ok, because APurify patches AllocMem()  &  FreeMem()  entries.  Thus  a
  337.     program can access to the bitplanes of one of its screen without error.
  338.  
  339.     If  the  program  makes  a  legal  access,   but   attributes    are
  340.     incompatible  with    the  access-kind,  a  protection-error    message  is
  341.     displayed. Actually only the first    kilobyte  is  read/write-protected.
  342.     But it may change in the future.
  343.  
  344.  
  345. HOW TO USE APURIFY:
  346. ------------------
  347.     One can see APurify as a pre-assembler. It must be used on assembly
  348.     language sourcefile just before the assembler takes place. It scan    the
  349.     file and change it a bit so that APur.a can be used.
  350.  
  351.     Normal way to use it for a C program is to:
  352.  
  353.     - compile C sourcefiles and leave assembly language source (.s).
  354.     - use APurify on each .s file.
  355.     - compile your .s file to get a .o file
  356.     - link all .o files together with APur.a.
  357.  
  358.     For example, using gcc on prog.c it gives
  359.  
  360.     CLI> gcc -g prog.c -o prog.s -S
  361.     CLI> APurify -tb prog.s
  362.     CLI> gcc -g prog.s -o prog -lAPur
  363.  
  364.     As you can see, APurify needs no change to your C files to be used.
  365.     In this realease you need no more  to  call  AP_Init()  in  the  main()
  366.     function. The call is automatically inserted when the main-entry  label
  367.     (specified by -mp) is found. You shoud not  use  dos.library/Exit()  to
  368.     abort your program, I think it'll crash if APurify is running.  If  you
  369.     must use Exit() then call AP_Close() just before  calling  Exit().  The
  370.     explantion is simple: since some system functions  are  patched,  if  a
  371.     program  exits  without  closing  the  library,  those  patch  will  be
  372.     corruped, pointing to a code that is nomore in memory and  you'll  meet
  373.     the guru (ie: the computer will crash)... (You've been warned :-).
  374.  
  375.     You can disable/enable printing of messages by    making    a  call  to
  376.     AP_Report(flag). If  flag  is  true  (ie.  different  from  zero)  then
  377.     printing is enabled, if it is false (ie. equal to zero), no output will
  378.     be done. This is usefull for startup-codes. For  example,  if  you    are
  379.     using the argv[] array in C,  APurify  will  make  a lot of false-error
  380.     printing. This is because the values pointed by this array is allocated
  381.     before  the  library   is    opened.   You  can avoid  this    by  calling
  382.     AP_Report(0) before (and AP_Report(1) after) the code that uses argv[].
  383.  
  384.     When debugging an APurify'ed program, you can put a  breakpoint  on
  385.     a function called AP_Err(). That function AP_Err() is called each  time
  386.     APurify detects an error. With that, you'll have the occasion  to  look
  387.     at your program just before a faultly memory-access occur.
  388.  
  389.     You can switch    from  a  verbose  output  to  a  shorter  one  with
  390.     AP_Verbose(flag). IF flag is true then the verbose mode is on. If it is
  391.     false then only short messages will be printed. Some people prefer    the
  392.     later so that is the default. If you perfer the verbose ouput then    put
  393.     AP_Verbose(1)  someware  in  your  code  and  you'll  get  some  longer
  394.     explanations about illegal accesses.
  395.  
  396.     You can specify a logfile where APurify can put its errors.  To  do
  397.     this, set the environment variable "APlog" (file ENV:APlog) to  a  name
  398.     of a logfile. If this variable is set, then APurify will append all its
  399.     outputs to the file indicated. If this variable does not  exists,  then
  400.     the standard error stream is used.
  401.  
  402.  
  403. EXAMPLE:
  404. -------
  405.     As an example,    let's  look  at  the  test  program  compiled  with
  406.     gcc-2.6.0. You'll see how you can use the APurify report it produces to
  407.     find what's wrong in the program.  For  this,  I've  included  in  that
  408.     document the commented report. My comments/explanations appear on lines
  409.     beginning with a "#".
  410.  
  411.     **** APurify started on Thu Jan  4 23:03:58 1996
  412.  
  413.     #
  414.     # Well, the report started...
  415.     #
  416.  
  417.     **** APURIFY ERROR ! [$0026defc(4) R-- (_main, PC=$0027eef0 HUNK=$0
  418.     OFFSET=$410)] accessed between:
  419.     -25      [$0026df18(27) RW- (_main)]
  420.     +1405      [$0026d920(96) RWS (segment Module CLI)]
  421.  
  422.     #
  423.     # Hum... First hit... it is an error in reading something in the main()
  424.     # procedure between two blocks already  allocated.    The  nearest  block
  425.     # appears in first position, so we can think that the error was done by
  426.     # accessing an array allocated in main() with a negative index. We  can
  427.     # look at the code to find what is wrong with it. Using DOBJ, we  found
  428.     # at offset $410 in the first hunk the following code:
  429.     #
  430.     #        00.00000410  24ab ffd8           MOVE.L -40(A3),(A2)
  431.     #
  432.     # This corresponds to the C code:
  433.     #
  434.     #                   a[0]=b[-10]
  435.     #
  436.     # Hence we've discovered a first error in the code. Note  that  -25  is
  437.     # the distance (in bytes) between the end of the  accessed  memory  and
  438.     # the beginning of the array. This is not the  difference  between    the
  439.     # beginning address of the two blocks!
  440.     #
  441.  
  442.     **** APURIFY ERROR ! [$00245f20(4) R-- (_main, PC=$0027ef1a HUNK=$0
  443.     OFFSET=$43a)] accessed between:
  444.     +1      [$00245f10(16) RW- (_main)]
  445.     -162301   [$0026d920(96) RWS (segment Module CLI)]
  446.  
  447.     #
  448.     # Well... here it seems to be an access just after an allocated  block.
  449.     # the offset +1 is the distance in bytes between the accessed block and
  450.     # a allocated block. The situation is like this:
  451.     #
  452.     #              ---------[ 1 ]( 2 )---------->
  453.     #
  454.     # Where "[ 1 ]" is the allocated block and "( 2 )" the accessed  block.
  455.     # If we look in the code, we find:
  456.     #
  457.     #        00.0000043a  4aaa 0004           TST.L   4(A2)
  458.     #
  459.     # that correponds to the test done by "if(a[1] == 0)". This is an error
  460.     # since the array 'a' is just 16-12=4 bytes long. So a[1] points out of
  461.     # the array!
  462.     #
  463.  
  464.     **** APURIFY ERROR ! [$00245f1e(4) R-- (_read_shifted, PC=$0027ed9e
  465.     HUNK=$0 OFFSET=$2be)] accessed across the ending boundary of:
  466.     -2      [$00245f10(16) RW- (_main)]
  467.  
  468.     #
  469.     # Hehe another error... Damn ! That test program is a  FULL  of  bug  !
  470.     # Yes, but that one is an other kind of error. It is an access across a
  471.     # boundary. That occur in the read_shifted() code. We need not look  in
  472.     # the asm file to see the  error.  Here  it  is  a    misaligment  error.
  473.     # Visually that gives:
  474.     #
  475.     #               ------------[ 1(]2 )----------->
  476.     #
  477.     #           [ 1 ] = allocated       ( 2 ) = accessed.
  478.     #
  479.  
  480.     **** APURIFY ERROR ! [$00245f1c(4) R-- (_read_long, PC=$0027edce
  481.     HUNK=$0 OFFSET=$2ee)] accessed between:
  482.     -162305   [$0026d920(96) RWS (segment Module CLI)]
  483.     +2382621  [$00000000(1024)    --S (Basic 680x0 vectors)]
  484.  
  485.     #
  486.     # That error is strange! It is  not  an  access  to  an  array  with  a
  487.     # negative index as one think immediately: We never call read_long() in
  488.     # such a way, and the offsets are too big ! Indeed, the accessed memory
  489.     # was right some times ago since it lays in the array 'a'  (look at the
  490.     # second hit).  Hence, it must be an access to a free()'d memory.  That
  491.     # error is then obviously found in the code:
  492.     #
  493.     #              free_arg(a); read_long(a).
  494.     #                   ^^^^^^^^^^^^
  495.     #
  496.  
  497.     **** APURIFY ERROR ! [$00000004(4) R-- (_read_page_zero, PC=$0027ee32
  498.     HUNK=$0 OFFSET=$352)] accessed on a read-protected block:
  499.     +4      [$00000000(1024)    --S (Basic 680x0 vectors)]
  500.  
  501.     #
  502.     # Here the error is obvious, were are reading the zero-page. If it    was
  503.     # in writing, that error would be very dangerous.
  504.     #
  505.  
  506.     **** APURIFY WARNING ! Closing library without deallocation of the
  507.     following block(s):
  508.     - [$00271540(412)   RW- (_main)]
  509.     - [$00287070(12012) RW- (_main)]
  510.     - [$0032e2c0(40012) RW- (_main)]
  511.  
  512.     #
  513.     # The program has exit()ed. APurify tells us that we've forget to  free
  514.     # those blocks. It    is  a  case  of  memory  leak.    Those  blocks  were
  515.     # allocated in main(). Those  were allocated and lost by
  516.     #
  517.     #           a=malloc(4),malloc(400),malloc(12000),malloc(400000)
  518.     #
  519.     # since the assignment only affects the first item of ",,,".
  520.     #
  521.  
  522.     **** APurify ended on Thu Jan  4 23:04:00 1996
  523.  
  524.     #
  525.     # Well... done :-).
  526.     #
  527.  
  528.  
  529. LEGAL PART:
  530. ----------
  531.     That program is provided 'AS IS'. I  am  not  responsible  for  any
  532.     dammage it can cause (but I am responsible for the benefits it can give
  533.     to you :-). Use that software at you own risks.
  534.  
  535.     That program is FREEWARE. You can use and distribute it as long  as
  536.     you keep the archive  intact  (no  adulteration  of  files  except  for
  537.     compression). It can't be sold without my agreement (except  a  minimal
  538.     amount for media support). You must ask me for commercial use  of  (any
  539.     part of) that product. I keep all my rights on  that  program  and    its
  540.     future releases. I can modify that software without telling it  to    the
  541.     users.
  542.  
  543.     If you wish, you can send me a postcard or anything else  you  want
  544.     (money, documentation, amiga, hardware  stuff,  ...)  in  exchange  for
  545.     using APurify. But there is no obligation :-). My postal address is:
  546.  
  547.         M. DEVULDER Samuel
  548.         1, Rue du chateau
  549.         59380 STEENE
  550.         FRANCE
  551.  
  552.     (yes I'm french !). You can  send  suggestions  or  bugs  to  my  email
  553.     address:
  554.  
  555.         devulder@info.unicaen.fr
  556.  
  557.  
  558. NOTES:
  559. -----
  560.     It has been compiled with cross-gcc 2.7.0  with  libnix  on  a    Sun
  561.     sparc.
  562.  
  563.     I had the idea of that program    after  a  chat    with  Cedric  BEUST
  564.     (AMIGA NEWS) on IRC (Internet Relay Chat). Thanks Cedric !
  565.  
  566.     I wish to thank Philippe Brand for his help in my port. I also wish
  567.     to thank J.C Hoehle for his usefull advices.
  568.  
  569.     All marks are proprietary of their respective owners.
  570.  
  571.     There are some programs like APurify. For example,  FORTIFY  (Simon
  572.     P. Bullen), but  it  only  detects    illegal  writes  to  boundaries  of
  573.     allocated blocks. Thus it can't detect big oversteps and  oversteps  in
  574.     reading and the detection is not real-time. Enforcer can detect illegal
  575.     access to memory, but it needs a special device (MMU).
  576.  
  577.  
  578. HINTS & TIPS:
  579. ------------
  580.     You can see some memory leaks with that version of APurify.  It  is
  581.     not really good but it can help. Memory leak  occur  when  a  block  of
  582.     memory is nomore pointed by your  program.    Those  memory  blocks  will
  583.     necessary be displayed when your  program  exit()s.  So  with  all  the
  584.     messages printed on that occasion, you can find such  blocks.  I  known
  585.     this is not so great, but I think it can help you a little    bit  (maybe
  586.     in a future version I'll build some code to really check memory leaks).
  587.  
  588.  
  589. BUGS:
  590. ----
  591.     APurify don't known public memory where a program can read or write
  592.     without having allocated it. Thus, it  will  report  an  error  when  a
  593.     program reads or writes values in a message obtained  through  GetMsg()
  594.     calls. Use AP_Report() to avoid such reports.
  595.  
  596.     It can display messages about closing the library  without  freeing
  597.     some memory blocks. This is due to printf() that allocates memory  that
  598.     is free'd on exit. This is not a real bug, but you can  avoid  this  by
  599.     doing a AP_Report(0) just before exiting. But you must notice  that  it
  600.     is better to display false bugs than to not display real ones.
  601.  
  602.     I've rewritten malloc()/realloc()/free().  I  hope  this  will  not
  603.     produce bugs (I've tested sucessfully the test program with  libnix and
  604.     ixemul, so I hope it will be all right).
  605.  
  606.     Certainly more bugs, but I'm waiting for your bug-reports.
  607.