LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/ucpp - mem.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 14 0.0 %
Date: 2012-12-17 Functions: 0 3 0.0 %
Legend: Lines: hit not hit

          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           0 : 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           0 :         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           0 :         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           0 : char *(sdup)(char *src)
     170             : {
     171           0 :         size_t n = 1 + strlen(src);
     172           0 :         char *x = getmem(n);
     173             : 
     174           0 :         mmv(x, src, n);
     175           0 :         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