LCOV - code coverage report
Current view: top level - workdir/unxlngi6.pro/CustomTarget/ucpp/source - mem.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 8 14 57.1 %
Date: 2012-08-25 Functions: 2 3 66.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1 4 25.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Memory manipulation routines
       3                 :            :  * (c) Thomas Pornin 1998 - 2002
       4                 :            :  *
       5                 :            :  * Redistribution and use in source and binary forms, with or without
       6                 :            :  * modification, are permitted provided that the following conditions
       7                 :            :  * are met:
       8                 :            :  * 1. Redistributions of source code must retain the above copyright
       9                 :            :  *    notice, this list of conditions and the following disclaimer.
      10                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      11                 :            :  *    notice, this list of conditions and the following disclaimer in the
      12                 :            :  *    documentation and/or other materials provided with the distribution.
      13                 :            :  * 4. The name of the authors may not be used to endorse or promote
      14                 :            :  *    products derived from this software without specific prior written
      15                 :            :  *    permission.
      16                 :            :  *
      17                 :            :  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 
      18                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
      19                 :            :  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      20                 :            :  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
      21                 :            :  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      22                 :            :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
      23                 :            :  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
      24                 :            :  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      25                 :            :  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
      26                 :            :  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
      27                 :            :  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      28                 :            :  *
      29                 :            :  */
      30                 :            : 
      31                 :            : #include "mem.h"
      32                 :            : #include <stdio.h>
      33                 :            : #include <stdlib.h>
      34                 :            : #include <string.h>
      35                 :            : 
      36                 :            : /*
      37                 :            :  * Shifting a pointer of that some bytes is supposed to satisfy
      38                 :            :  * alignment requirements. This is *not* guaranteed by the standard
      39                 :            :  * but should work everywhere anyway.
      40                 :            :  */
      41                 :            : #define ALIGNSHIFT      (sizeof(long) > sizeof(long double) \
      42                 :            :                         ? sizeof(long) : sizeof(long double))
      43                 :            : 
      44                 :            : #ifdef AUDIT
      45                 :            : void die(void)
      46                 :            : {
      47                 :            :         abort();
      48                 :            : }
      49                 :            : 
      50                 :            : static void suicide(unsigned long e)
      51                 :            : {
      52                 :            :         fprintf(stderr, "ouch: Schrodinger's beef is not dead ! %lx\n", e);
      53                 :            :         die();
      54                 :            : }
      55                 :            : #else
      56                 :          0 : void die(void)
      57                 :            : {
      58                 :          0 :         exit(EXIT_FAILURE);
      59                 :            : }
      60                 :            : #endif
      61                 :            : 
      62                 :            : #if defined AUDIT || defined MEM_CHECK || defined MEM_DEBUG
      63                 :            : /*
      64                 :            :  * This function is equivalent to a malloc(), but will display an error
      65                 :            :  * message and exit if the wanted memory is not available
      66                 :            :  */
      67                 :            : #ifdef MEM_DEBUG
      68                 :            : static void *getmem_raw(size_t x)
      69                 :            : #else
      70                 :            : void *(getmem)(size_t x)
      71                 :            : #endif
      72                 :            : {
      73                 :            :         void *m;
      74                 :            : 
      75                 :            : #ifdef AUDIT
      76                 :            :         m = malloc(x + ALIGNSHIFT);
      77                 :            : #else
      78                 :            :         m = malloc(x);
      79                 :            : #endif
      80                 :            :         if (m == 0) {
      81                 :            :                 fprintf(stderr, "ouch: malloc() failed\n");
      82                 :            :                 die();
      83                 :            :         }
      84                 :            : #ifdef AUDIT
      85                 :            :         *((unsigned long *)m) = 0xdeadbeefUL;
      86                 :            :         return (void *)(((char *)m) + ALIGNSHIFT);
      87                 :            : #else
      88                 :            :         return m;
      89                 :            : #endif
      90                 :            : }
      91                 :            : #endif
      92                 :            : 
      93                 :            : #ifndef MEM_DEBUG
      94                 :            : /*
      95                 :            :  * This function is equivalent to a realloc(); if the realloc() call
      96                 :            :  * fails, it will try a malloc() and a memcpy(). If not enough memory is
      97                 :            :  * available, the program exits with an error message
      98                 :            :  */
      99                 :      99436 : void *(incmem)(void *m, size_t x, size_t nx)
     100                 :            : {
     101                 :            :         void *nm;
     102                 :            : 
     103                 :            : #ifdef AUDIT
     104                 :            :         m = (void *)(((char *)m) - ALIGNSHIFT);
     105                 :            :         if (*((unsigned long *)m) != 0xdeadbeefUL)
     106                 :            :                 suicide(*((unsigned long *)m));
     107                 :            :         x += ALIGNSHIFT; nx += ALIGNSHIFT;
     108                 :            : #endif
     109         [ -  + ]:      99436 :         if (!(nm = realloc(m, nx))) {
     110         [ #  # ]:          0 :                 if (x > nx) x = nx;
     111                 :          0 :                 nm = (getmem)(nx);
     112                 :          0 :                 memcpy(nm, m, x);
     113                 :            :                 /* free() and not freemem(), because of the Schrodinger beef */
     114                 :          0 :                 free(m);
     115                 :            :         }
     116                 :            : #ifdef AUDIT
     117                 :            :         return (void *)(((char *)nm) + ALIGNSHIFT);
     118                 :            : #else
     119                 :      99436 :         return nm;
     120                 :            : #endif
     121                 :            : }
     122                 :            : #endif
     123                 :            : 
     124                 :            : #if defined AUDIT || defined MEM_DEBUG
     125                 :            : /*
     126                 :            :  * This function frees the given block
     127                 :            :  */
     128                 :            : #ifdef MEM_DEBUG
     129                 :            : static void freemem_raw(void *x)
     130                 :            : #else
     131                 :            : void (freemem)(void *x)
     132                 :            : #endif
     133                 :            : {
     134                 :            : #ifdef AUDIT
     135                 :            :         void *y = (void *)(((char *)x) - ALIGNSHIFT);
     136                 :            : 
     137                 :            :         if ((*((unsigned long *)y)) != 0xdeadbeefUL)
     138                 :            :                 suicide(*((unsigned long *)y));
     139                 :            :         *((unsigned long *)y) = 0xfeedbabeUL;
     140                 :            :         free(y);
     141                 :            : #else
     142                 :            :         free(x);
     143                 :            : #endif
     144                 :            : }
     145                 :            : #endif
     146                 :            : 
     147                 :            : #ifdef AUDIT
     148                 :            : /*
     149                 :            :  * This function copies n bytes from src to dest
     150                 :            :  */
     151                 :            : void *mmv(void *dest, void *src, size_t n)
     152                 :            : {
     153                 :            :         return memcpy(dest, src, n);
     154                 :            : }
     155                 :            : 
     156                 :            : /*
     157                 :            :  * This function copies n bytes from src to dest
     158                 :            :  */
     159                 :            : void *mmvwo(void *dest, void *src, size_t n)
     160                 :            : {
     161                 :            :         return memmove(dest, src, n);
     162                 :            : }
     163                 :            : #endif
     164                 :            : 
     165                 :            : #ifndef MEM_DEBUG
     166                 :            : /*
     167                 :            :  * This function creates a new char * and fills it with a copy of src
     168                 :            :  */
     169                 :     241104 : char *(sdup)(char *src)
     170                 :            : {
     171                 :     241104 :         size_t n = 1 + strlen(src);
     172                 :     241104 :         char *x = getmem(n);
     173                 :            : 
     174                 :     241104 :         mmv(x, src, n);
     175                 :     241104 :         return x;
     176                 :            : }
     177                 :            : #endif
     178                 :            : 
     179                 :            : #ifdef MEM_DEBUG
     180                 :            : /*
     181                 :            :  * We include here special versions of getmem(), freemem() and incmem()
     182                 :            :  * that track allocations and are used to detect memory leaks.
     183                 :            :  *
     184                 :            :  * Each allocation is referenced in a list, with a serial number.
     185                 :            :  */
     186                 :            : 
     187                 :            : /*
     188                 :            :  * Define "true" functions for applications that need pointers
     189                 :            :  * to such functions.
     190                 :            :  */
     191                 :            : void *(getmem)(size_t n)
     192                 :            : {
     193                 :            :         return getmem(n);
     194                 :            : }
     195                 :            : 
     196                 :            : void (freemem)(void *x)
     197                 :            : {
     198                 :            :         freemem(x);
     199                 :            : }
     200                 :            : 
     201                 :            : void *(incmem)(void *x, size_t s, size_t ns)
     202                 :            : {
     203                 :            :         return incmem(x, s, ns);
     204                 :            : }
     205                 :            : 
     206                 :            : char *(sdup)(char *s)
     207                 :            : {
     208                 :            :         return sdup(s);
     209                 :            : }
     210                 :            : 
     211                 :            : static long current_serial = 0L;
     212                 :            : 
     213                 :            : /* must be a power of two */
     214                 :            : #define MEMDEBUG_MEMG   128U
     215                 :            : 
     216                 :            : static struct mem_track {
     217                 :            :         void *block;
     218                 :            :         long serial;
     219                 :            :         char *file;
     220                 :            :         int line;
     221                 :            : } *mem = 0;
     222                 :            : 
     223                 :            : static size_t meml = 0;
     224                 :            : 
     225                 :            : static unsigned int current_ptr = 0;
     226                 :            : 
     227                 :            : static void *true_incmem(void *x, size_t old_size, size_t new_size)
     228                 :            : {
     229                 :            :         void * y = realloc(x, new_size);
     230                 :            : 
     231                 :            :         if (y == 0) {
     232                 :            :                 y = malloc(new_size);
     233                 :            :                 if (y == 0) {
     234                 :            :                         fprintf(stderr, "ouch: malloc() failed\n");
     235                 :            :                         die();
     236                 :            :                 }
     237                 :            :                 mmv(y, x, old_size < new_size ? old_size : new_size);
     238                 :            :                 free(x);
     239                 :            :         }
     240                 :            :         return y;
     241                 :            : }
     242                 :            : 
     243                 :            : static long find_free_block(void)
     244                 :            : {
     245                 :            :         unsigned int n;
     246                 :            :         size_t i;
     247                 :            : 
     248                 :            :         for (i = 0, n = current_ptr; i < meml; i ++) {
     249                 :            :                 if (mem[n].block == 0) {
     250                 :            :                         current_ptr = n;
     251                 :            :                         return n;
     252                 :            :                 }
     253                 :            :                 n = (n + 1) & (meml - 1U);
     254                 :            :         }
     255                 :            :         if (meml == 0) {
     256                 :            :                 size_t j;
     257                 :            : 
     258                 :            :                 meml = MEMDEBUG_MEMG;
     259                 :            :                 mem = malloc(meml * sizeof(struct mem_track));
     260                 :            :                 current_ptr = 0;
     261                 :            :                 for (j = 0; j < meml ; j ++) mem[j].block = 0;
     262                 :            :         } else {
     263                 :            :                 size_t j;
     264                 :            : 
     265                 :            :                 mem = true_incmem(mem, meml * sizeof(struct mem_track),
     266                 :            :                         2 * meml * sizeof(struct mem_track));
     267                 :            :                 current_ptr = meml;
     268                 :            :                 for (j = meml; j < 2 * meml ; j ++) mem[j].block = 0;
     269                 :            :                 meml *= 2;
     270                 :            :         }
     271                 :            :         return current_ptr;
     272                 :            : }
     273                 :            : 
     274                 :            : void *getmem_debug(size_t n, char *file, int line)
     275                 :            : {
     276                 :            :         void *x = getmem_raw(n + ALIGNSHIFT);
     277                 :            :         long i = find_free_block();
     278                 :            : 
     279                 :            :         *(long *)x = i;
     280                 :            :         mem[i].block = x;
     281                 :            :         mem[i].serial = current_serial ++;
     282                 :            :         mem[i].file = file;
     283                 :            :         mem[i].line = line;
     284                 :            :         return (void *)((unsigned char *)x + ALIGNSHIFT);
     285                 :            : }
     286                 :            : 
     287                 :            : void freemem_debug(void *x, char *file, int line)
     288                 :            : {
     289                 :            :         void *y = (unsigned char *)x - ALIGNSHIFT;
     290                 :            :         long i = *(long *)y;
     291                 :            : 
     292                 :            :         if (i < 0 || (size_t)i >= meml || mem[i].block != y) {
     293                 :            :                 fprintf(stderr, "ouch: freeing free people (from %s:%d)\n",
     294                 :            :                         file, line);
     295                 :            :                 die();
     296                 :            :         }
     297                 :            :         mem[i].block = 0;
     298                 :            :         freemem_raw(y);
     299                 :            : }
     300                 :            : 
     301                 :            : void *incmem_debug(void *x, size_t ol, size_t nl, char *file, int line)
     302                 :            : {
     303                 :            :         void *y = getmem_debug(nl, file, line);
     304                 :            :         mmv(y, x, ol < nl ? ol : nl);
     305                 :            :         freemem_debug(x, file, line);
     306                 :            :         return y;
     307                 :            : }
     308                 :            : 
     309                 :            : char *sdup_debug(char *src, char *file, int line)
     310                 :            : {
     311                 :            :         size_t n = 1 + strlen(src);
     312                 :            :         char *x = getmem_debug(n, file, line);
     313                 :            : 
     314                 :            :         mmv(x, src, n);
     315                 :            :         return x;
     316                 :            : }
     317                 :            : 
     318                 :            : void report_leaks(void)
     319                 :            : {
     320                 :            :         size_t i;
     321                 :            : 
     322                 :            :         for (i = 0; i < meml; i ++) {
     323                 :            :                 if (mem[i].block) fprintf(stderr, "leak: serial %ld, %s:%d\n",
     324                 :            :                         mem[i].serial, mem[i].file, mem[i].line);
     325                 :            :         }
     326                 :            : }
     327                 :            : 
     328                 :            : #endif

Generated by: LCOV version 1.10