2011-03-27 Ivan Maidanski <ivmai@mail.ru>
authorivmai <ivmai>
Sun, 27 Mar 2011 20:19:47 +0000 (20:19 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 26 Jul 2011 17:06:57 +0000 (21:06 +0400)
* dbg_mlc.c (GC_debug_strdup, GC_debug_free): Output a portability
warning if the argument is NULL and GC is in leaks detection mode.
* dbg_mlc.c (GC_debug_strndup, GC_debug_wcsdup): New public
function definition.
* malloc.c (GC_strndup, GC_wcsdup, strndup): Ditto.
* mallocx.c (GC_posix_memalign): Ditto.
* malloc.c (strdup): Fix string size value; rename "len" to "lb".
* mallocx.c: Include errno.h unless WinCE (otherwise include
windows.h for Win32 error constants).
* win32_threads.c: Define WIN32_LEAN_AND_MEAN and NOSERVICE before
windows.h inclusion.
* misc.c (GC_init): Register at-exit callback if GC_find_leak
(even if GC_FIND_LEAK macro is unset).
* pthread_stop_world.c (NACL_STORE_REGS,
__nacl_suspend_thread_if_needed, GC_nacl_initialize_gc_thread):
Use BCOPY() instead of memcpy().
* pthread_support.c (GC_init_real_syms): Ditto.
* doc/README: Update year in copyright.
* include/gc.h: Ditto.
* doc/README.macros (GC_DEBUG_REPLACEMENT, GC_REQUIRE_WCSDUP):
Document new macro.
* doc/README.macros (REDIRECT_MALLOC): Update documentation.
* include/gc.h (GC_strndup, GC_posix_memalign, GC_debug_strndup):
New API function prototype.
* include/gc.h (GC_MALLOC, GC_REALLOC): Redirect to
GC_debug_malloc/realloc_replacement() if GC_DEBUG_REPLACEMENT.
* include/gc.h (GC_STRDUP): Remove redundant parentheses.
* include/leak_detector.h (realloc, strdup): Ditto.
* include/gc.h (GC_STRNDUP): New API macro.
* include/gc.h (GC_NEW, GC_NEW_ATOMIC, GC_NEW_STUBBORN,
GC_NEW_UNCOLLECTABLE): Add missing parentheses.
* include/gc.h (GC_wcsdup, GC_debug_wcsdup): New API function
prototype (only if GC_REQUIRE_WCSDUP).
* include/gc.h (GC_WCSDUP): New API macro (only if
GC_REQUIRE_WCSDUP).
* include/leak_detector.h: Add copyright header; add usage
comment; include stdlib.h and string.h after gc.h (unless
GC_DONT_INCLUDE_STDLIB).
* include/leak_detector.h (malloc, calloc, free, realloc):
Undefine symbol before its redefinition.
* include/leak_detector.h (strndup, memalign, posix_memalign):
Redefine to the corresponding GC function.
* include/leak_detector.h (wcsdup): Redefine to GC_WCSDUP (only
if GC_REQUIRE_WCSDUP).
* include/leak_detector.h (CHECK_LEAKS): Add comment; don't define
the macro if already defined.

12 files changed:
ChangeLog
dbg_mlc.c
doc/README
doc/README.macros
include/gc.h
include/leak_detector.h
malloc.c
mallocx.c
misc.c
pthread_stop_world.c
pthread_support.c
win32_threads.c

index e4765d1..02b53a8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,52 @@
+2011-03-27  Ivan Maidanski  <ivmai@mail.ru>
+
+       * dbg_mlc.c (GC_debug_strdup, GC_debug_free): Output a portability
+       warning if the argument is NULL and GC is in leaks detection mode.
+       * dbg_mlc.c (GC_debug_strndup, GC_debug_wcsdup): New public
+       function definition.
+       * malloc.c (GC_strndup, GC_wcsdup, strndup): Ditto.
+       * mallocx.c (GC_posix_memalign): Ditto.
+       * malloc.c (strdup): Fix string size value; rename "len" to "lb".
+       * mallocx.c: Include errno.h unless WinCE (otherwise include
+       windows.h for Win32 error constants).
+       * win32_threads.c: Define WIN32_LEAN_AND_MEAN and NOSERVICE before
+       windows.h inclusion.
+       * misc.c (GC_init): Register at-exit callback if GC_find_leak
+       (even if GC_FIND_LEAK macro is unset).
+       * pthread_stop_world.c (NACL_STORE_REGS,
+       __nacl_suspend_thread_if_needed, GC_nacl_initialize_gc_thread):
+       Use BCOPY() instead of memcpy().
+       * pthread_support.c (GC_init_real_syms): Ditto.
+       * doc/README: Update year in copyright.
+       * include/gc.h: Ditto.
+       * doc/README.macros (GC_DEBUG_REPLACEMENT, GC_REQUIRE_WCSDUP):
+       Document new macro.
+       * doc/README.macros (REDIRECT_MALLOC): Update documentation.
+       * include/gc.h (GC_strndup, GC_posix_memalign, GC_debug_strndup):
+       New API function prototype.
+       * include/gc.h (GC_MALLOC, GC_REALLOC): Redirect to
+       GC_debug_malloc/realloc_replacement() if GC_DEBUG_REPLACEMENT.
+       * include/gc.h (GC_STRDUP): Remove redundant parentheses.
+       * include/leak_detector.h (realloc, strdup): Ditto.
+       * include/gc.h (GC_STRNDUP): New API macro.
+       * include/gc.h (GC_NEW, GC_NEW_ATOMIC, GC_NEW_STUBBORN,
+       GC_NEW_UNCOLLECTABLE): Add missing parentheses.
+       * include/gc.h (GC_wcsdup, GC_debug_wcsdup): New API function
+       prototype (only if GC_REQUIRE_WCSDUP).
+       * include/gc.h (GC_WCSDUP): New API macro (only if
+       GC_REQUIRE_WCSDUP).
+       * include/leak_detector.h: Add copyright header; add usage
+       comment; include stdlib.h and string.h after gc.h (unless
+       GC_DONT_INCLUDE_STDLIB).
+       * include/leak_detector.h (malloc, calloc, free, realloc):
+       Undefine symbol before its redefinition.
+       * include/leak_detector.h (strndup, memalign, posix_memalign):
+       Redefine to the corresponding GC function.
+       * include/leak_detector.h (wcsdup): Redefine to GC_WCSDUP (only
+       if GC_REQUIRE_WCSDUP).
+       * include/leak_detector.h (CHECK_LEAKS): Add comment; don't define
+       the macro if already defined.
+
 2011-03-22  Ivan Maidanski  <ivmai@mail.ru>
 
        * misc.c (GC_abort): Use _exit() (instead of DebugBreak) on Win32 when
index e1bd4a0..d4db3b3 100644 (file)
--- a/dbg_mlc.c
+++ b/dbg_mlc.c
@@ -661,25 +661,66 @@ GC_API void * GC_CALL GC_debug_malloc_atomic(size_t lb, GC_EXTRA_PARAMS)
 
 GC_API char * GC_CALL GC_debug_strdup(const char *str, GC_EXTRA_PARAMS)
 {
-    char *copy;
-    size_t lb;
-    if (str == NULL) return NULL;
-    lb = strlen(str) + 1;
-    copy = GC_debug_malloc_atomic(lb, OPT_RA s, i);
+  char *copy;
+  size_t lb;
+  if (str == NULL) {
+    if (GC_find_leak)
+      WARN("strdup(NULL) behavior is undefined\n", 0);
+    return NULL;
+  }
+  lb = strlen(str) + 1;
+  copy = GC_debug_malloc_atomic(lb, OPT_RA s, i);
+  if (copy == NULL) {
+#   ifndef MSWINCE
+      errno = ENOMEM;
+#   endif
+    return NULL;
+  }
+# ifndef MSWINCE
+    strcpy(copy, str);
+# else
+    /* strcpy() is deprecated in WinCE */
+    memcpy(copy, str, lb);
+# endif
+  return copy;
+}
+
+GC_API char * GC_CALL GC_debug_strndup(const char *str, size_t size,
+                                       GC_EXTRA_PARAMS)
+{
+  char *copy;
+  size_t len = strlen(str); /* str is expected to be non-NULL  */
+  if (len > size)
+    len = size;
+  copy = GC_debug_malloc_atomic(len + 1, OPT_RA s, i);
+  if (copy == NULL) {
+#   ifndef MSWINCE
+      errno = ENOMEM;
+#   endif
+    return NULL;
+  }
+  BCOPY(str, copy, len);
+  copy[len] = '\0';
+  return copy;
+}
+
+#ifdef GC_REQUIRE_WCSDUP
+# include <wchar.h> /* for wcslen() */
+
+  GC_API wchar_t * GC_CALL GC_debug_wcsdup(const wchar_t *str, GC_EXTRA_PARAMS)
+  {
+    size_t lb = (wcslen(str) + 1) * sizeof(wchar_t);
+    wchar_t *copy = GC_debug_malloc_atomic(lb, OPT_RA s, i);
     if (copy == NULL) {
 #     ifndef MSWINCE
         errno = ENOMEM;
 #     endif
       return NULL;
     }
-#   ifndef MSWINCE
-      strcpy(copy, str);
-#   else
-      /* strcpy() is deprecated in WinCE */
-      memcpy(copy, str, lb);
-#   endif
+    BCOPY(str, copy, lb);
     return copy;
-}
+  }
+#endif /* GC_REQUIRE_WCSDUP */
 
 GC_API void * GC_CALL GC_debug_malloc_uncollectable(size_t lb,
                                                     GC_EXTRA_PARAMS)
@@ -729,7 +770,11 @@ GC_API void GC_CALL GC_debug_free(void * p)
       ptr_t clobbered;
 #   endif
 
-    if (0 == p) return;
+    if (0 == p) {
+      if (GC_find_leak)
+        WARN("free(NULL) is non-portable\n", 0);
+      return;
+    }
     base = GC_base(p);
     if (base == 0) {
         GC_err_printf("Attempt to free invalid pointer %p\n", p);
index 4a4ff77..5ca93f0 100644 (file)
@@ -1,7 +1,7 @@
 Copyright (c) 1988, 1989 Hans-J. Boehm, Alan J. Demers
 Copyright (c) 1991-1996 by Xerox Corporation.  All rights reserved.
 Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.
-Copyright (c) 1999-2005 Hewlett-Packard Development Company, L.P.
+Copyright (c) 1999-2011 by Hewlett-Packard Development Company.
 
 The file linux_threads.c is also
 Copyright (c) 1998 by Fergus Henderson.  All rights reserved.
index ee42f4e..ac78897 100644 (file)
@@ -30,6 +30,9 @@ MACRO           EXPLANATION
 GC_DEBUG        Tested by gc.h.  Causes all-upper-case macros to
                 expand to calls to debug versions of collector routines.
 
+GC_DEBUG_REPLACEMENT    Tested by gc.h. Causes GC_MALLOC/REALLOC() to be
+                defined as GC_debug_malloc/realloc_replacement().
+
 GC_NO_THREAD_REDIRECTS  Tested by gc.h.  Prevents redirection of thread
                 creation routines etc. to GC_ versions.  Requires the
                 programmer to explicitly handle thread registration.
@@ -73,6 +76,9 @@ GC_NOT_DLL      User-settable macro that overrides _DLL, e.g. if runtime
                 dynamic libraries are used, but the collector is in a static
                 library.  Tested by gc_config_macros.h.
 
+GC_REQUIRE_WCSDUP       Force GC to export GC_wcsdup() (the Unicode version
+                of GC_strdup); could be useful in the leak-finding mode.
+
 
 These define arguments influence the collector configuration:
 FIND_LEAK causes GC_find_leak to be initially set.
@@ -188,7 +194,7 @@ GC_NO_OPERATOR_NEW_ARRAY        Declares that the C++ compiler does not
 REDIRECT_MALLOC=<X>     Causes malloc to be defined as alias for X.
   Unless the following macros are defined, realloc is also redirected
   to GC_realloc, and free is redirected to GC_free.
-  Calloc and strdup are redefined in terms of the new malloc.  X should
+  Calloc and str[n]dup are redefined in terms of the new malloc.  X should
   be either GC_malloc or GC_malloc_uncollectable, or
   GC_debug_malloc_replacement.  (The latter invokes GC_debug_malloc
   with dummy source location information, but still results in
index 3f404b2..2354acd 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright 1996-1999 by Silicon Graphics.  All rights reserved.
  * Copyright 1999 by Hewlett-Packard Company.  All rights reserved.
  * Copyright (C) 2007 Free Software Foundation, Inc
- * Copyright (c) 2000-2010 by Hewlett-Packard Development Company.
+ * Copyright (c) 2000-2011 by Hewlett-Packard Development Company.
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
@@ -352,6 +352,7 @@ GC_API void * GC_CALL GC_malloc(size_t /* size_in_bytes */)
 GC_API void * GC_CALL GC_malloc_atomic(size_t /* size_in_bytes */)
                         GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1);
 GC_API char * GC_CALL GC_strdup(const char *) GC_ATTR_MALLOC;
+GC_API char * GC_CALL GC_strndup(const char *, size_t) GC_ATTR_MALLOC;
 GC_API void * GC_CALL GC_malloc_uncollectable(size_t /* size_in_bytes */)
                         GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1);
 GC_API void * GC_CALL GC_malloc_stubborn(size_t /* size_in_bytes */)
@@ -360,6 +361,8 @@ GC_API void * GC_CALL GC_malloc_stubborn(size_t /* size_in_bytes */)
 /* GC_memalign() is not well tested.                                    */
 GC_API void * GC_CALL GC_memalign(size_t /* align */, size_t /* lb */)
                         GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(2);
+GC_API int GC_CALL GC_posix_memalign(void ** /* memptr */, size_t /* align */,
+                        size_t /* lb */);
 
 /* The following is only defined if the library has been suitably       */
 /* compiled:                                                            */
@@ -604,6 +607,8 @@ GC_API void * GC_CALL GC_debug_malloc_atomic(size_t /* size_in_bytes */,
                         GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1);
 GC_API char * GC_CALL GC_debug_strdup(const char *,
                                       GC_EXTRA_PARAMS) GC_ATTR_MALLOC;
+GC_API char * GC_CALL GC_debug_strndup(const char *, size_t,
+                                       GC_EXTRA_PARAMS) GC_ATTR_MALLOC;
 GC_API void * GC_CALL GC_debug_malloc_uncollectable(
                         size_t /* size_in_bytes */, GC_EXTRA_PARAMS)
                         GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1);
@@ -641,17 +646,27 @@ GC_API void * GC_CALL GC_debug_realloc_replacement(void * /* object_addr */,
                                                    size_t /* size_in_bytes */)
                         /* 'realloc' attr */ GC_ATTR_ALLOC_SIZE(2);
 
-#ifdef GC_DEBUG
+#ifdef GC_DEBUG_REPLACEMENT
+# define GC_MALLOC(sz) GC_debug_malloc_replacement(sz)
+# define GC_REALLOC(old, sz) GC_debug_realloc_replacement(old, sz)
+#elif defined(GC_DEBUG)
 # define GC_MALLOC(sz) GC_debug_malloc(sz, GC_EXTRAS)
+# define GC_REALLOC(old, sz) GC_debug_realloc(old, sz, GC_EXTRAS)
+#else
+# define GC_MALLOC(sz) GC_malloc(sz)
+# define GC_REALLOC(old, sz) GC_realloc(old, sz)
+#endif /* !GC_DEBUG_REPLACEMENT && !GC_DEBUG */
+
+#ifdef GC_DEBUG
 # define GC_MALLOC_ATOMIC(sz) GC_debug_malloc_atomic(sz, GC_EXTRAS)
-# define GC_STRDUP(s) GC_debug_strdup((s), GC_EXTRAS)
+# define GC_STRDUP(s) GC_debug_strdup(s, GC_EXTRAS)
+# define GC_STRNDUP(s, sz) GC_debug_strndup(s, sz, GC_EXTRAS)
 # define GC_MALLOC_UNCOLLECTABLE(sz) \
                         GC_debug_malloc_uncollectable(sz, GC_EXTRAS)
 # define GC_MALLOC_IGNORE_OFF_PAGE(sz) \
                         GC_debug_malloc_ignore_off_page(sz, GC_EXTRAS)
 # define GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(sz) \
                         GC_debug_malloc_atomic_ignore_off_page(sz, GC_EXTRAS)
-# define GC_REALLOC(old, sz) GC_debug_realloc(old, sz, GC_EXTRAS)
 # define GC_FREE(p) GC_debug_free(p)
 # define GC_REGISTER_FINALIZER(p, f, d, of, od) \
       GC_debug_register_finalizer(p, f, d, of, od)
@@ -668,15 +683,14 @@ GC_API void * GC_CALL GC_debug_realloc_replacement(void * /* object_addr */,
       GC_general_register_disappearing_link(link, GC_base(obj))
 # define GC_REGISTER_DISPLACEMENT(n) GC_debug_register_displacement(n)
 #else
-# define GC_MALLOC(sz) GC_malloc(sz)
 # define GC_MALLOC_ATOMIC(sz) GC_malloc_atomic(sz)
 # define GC_STRDUP(s) GC_strdup(s)
+# define GC_STRNDUP(s, sz) GC_strndup(s, sz)
 # define GC_MALLOC_UNCOLLECTABLE(sz) GC_malloc_uncollectable(sz)
 # define GC_MALLOC_IGNORE_OFF_PAGE(sz) \
                         GC_malloc_ignore_off_page(sz)
 # define GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(sz) \
                         GC_malloc_atomic_ignore_off_page(sz)
-# define GC_REALLOC(old, sz) GC_realloc(old, sz)
 # define GC_FREE(p) GC_free(p)
 # define GC_REGISTER_FINALIZER(p, f, d, of, od) \
       GC_register_finalizer(p, f, d, of, od)
@@ -692,16 +706,29 @@ GC_API void * GC_CALL GC_debug_realloc_replacement(void * /* object_addr */,
 # define GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) \
       GC_general_register_disappearing_link(link, obj)
 # define GC_REGISTER_DISPLACEMENT(n) GC_register_displacement(n)
-#endif
+#endif /* !GC_DEBUG */
 
 /* The following are included because they are often convenient, and    */
 /* reduce the chance for a misspecified size argument.  But calls may   */
 /* expand to something syntactically incorrect if t is a complicated    */
 /* type expression.                                                     */
-#define GC_NEW(t) (t *)GC_MALLOC(sizeof (t))
-#define GC_NEW_ATOMIC(t) (t *)GC_MALLOC_ATOMIC(sizeof (t))
-#define GC_NEW_STUBBORN(t) (t *)GC_MALLOC_STUBBORN(sizeof (t))
-#define GC_NEW_UNCOLLECTABLE(t) (t *)GC_MALLOC_UNCOLLECTABLE(sizeof (t))
+#define GC_NEW(t)               ((t*)GC_MALLOC(sizeof(t)))
+#define GC_NEW_ATOMIC(t)        ((t*)GC_MALLOC_ATOMIC(sizeof(t)))
+#define GC_NEW_STUBBORN(t)      ((t*)GC_MALLOC_STUBBORN(sizeof(t)))
+#define GC_NEW_UNCOLLECTABLE(t) ((t*)GC_MALLOC_UNCOLLECTABLE(sizeof(t)))
+
+#ifdef GC_REQUIRE_WCSDUP
+  /* This might be unavailable on some targets (or not needed). */
+  /* wchar_t should be defined in stddef.h */
+  GC_API wchar_t * GC_CALL GC_wcsdup(const wchar_t *) GC_ATTR_MALLOC;
+  GC_API wchar_t * GC_CALL GC_debug_wcsdup(const wchar_t *,
+                                           GC_EXTRA_PARAMS) GC_ATTR_MALLOC;
+# ifdef GC_DEBUG
+#   define GC_WCSDUP(s) GC_debug_wcsdup(s, GC_EXTRAS)
+# else
+#   define GC_WCSDUP(s) GC_wcsdup(s)
+# endif
+#endif /* GC_REQUIRE_WCSDUP */
 
 /* Finalization.  Some of these primitives are grossly unsafe.          */
 /* The idea is to make them both cheap, and sufficient to build         */
index 1d02f40..5540c22 100644 (file)
@@ -1,9 +1,68 @@
-#define GC_DEBUG
+/*
+ * Copyright (c) 2000-2011 by Hewlett-Packard Development Company.
+ * All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+#ifndef GC_LEAK_DETECTOR_H
+#define GC_LEAK_DETECTOR_H
+
+/* Include leak_detector.h (eg., via GCC --include directive)   */
+/* to turn BoehmGC into a Leak Detector.                        */
+
+#ifndef GC_DEBUG
+# define GC_DEBUG
+#endif
 #include "gc.h"
+
+#ifndef GC_DONT_INCLUDE_STDLIB
+  /* We ensure stdlib.h and string.h are included before        */
+  /* redirecting malloc() and the accompanying functions.       */
+# include <stdlib.h>
+# include <string.h>
+#endif
+
+#undef malloc
 #define malloc(n) GC_MALLOC(n)
+#undef calloc
 #define calloc(m,n) GC_MALLOC((m)*(n))
+#undef free
 #define free(p) GC_FREE(p)
-#define realloc(p,n) GC_REALLOC((p),(n))
+#undef realloc
+#define realloc(p,n) GC_REALLOC(p,n)
+
 #undef strdup
-#define strdup(s) GC_STRDUP((s))
-#define CHECK_LEAKS() GC_gcollect()
+#define strdup(s) GC_STRDUP(s)
+#undef strndup
+#define strndup(s,n) GC_STRNDUP(s,n)
+
+#ifdef GC_REQUIRE_WCSDUP
+  /* The collector should be built with GC_REQUIRE_WCSDUP       */
+  /* defined as well to redirect wcsdup().                      */
+# include <wchar.h>
+# undef wcsdup
+# define wcsdup(s) GC_WCSDUP(s)
+#endif
+
+#undef memalign
+#define memalign(a,n) GC_memalign(a,n)
+#undef posix_memalign
+#define posix_memalign(p,a,n) GC_posix_memalign(p,a,n)
+
+#ifndef CHECK_LEAKS
+# define CHECK_LEAKS() GC_gcollect()
+  /* Note 1: CHECK_LEAKS does not have GC prefix (preserved for */
+  /* backward compatibility).                                   */
+  /* Note 2: GC_gcollect() is also called automatically in the  */
+  /* leak-finding mode at program exit.                         */
+#endif
+
+#endif /* GC_LEAK_DETECTOR_H */
index 8109c99..026e3f9 100644 (file)
--- a/malloc.c
+++ b/malloc.c
@@ -255,6 +255,42 @@ GC_API char * GC_CALL GC_strdup(const char *s)
   return copy;
 }
 
+GC_API char * GC_CALL GC_strndup(const char *str, size_t size)
+{
+  char *copy;
+  size_t len = strlen(str); /* str is expected to be non-NULL  */
+  if (len > size)
+    len = size;
+  copy = GC_malloc_atomic(len + 1);
+  if (copy == NULL) {
+#   ifndef MSWINCE
+      errno = ENOMEM;
+#   endif
+    return NULL;
+  }
+  BCOPY(str, copy, len);
+  copy[len] = '\0';
+  return copy;
+}
+
+#ifdef GC_REQUIRE_WCSDUP
+# include <wchar.h> /* for wcslen() */
+
+  GC_API wchar_t * GC_CALL GC_wcsdup(const wchar_t *str)
+  {
+    size_t lb = (wcslen(str) + 1) * sizeof(wchar_t);
+    wchar_t *copy = GC_malloc_atomic(lb);
+    if (copy == NULL) {
+#     ifndef MSWINCE
+        errno = ENOMEM;
+#     endif
+      return NULL;
+    }
+    BCOPY(str, copy, lb);
+    return copy;
+  }
+#endif /* GC_REQUIRE_WCSDUP */
+
 /* Allocate lb bytes of composite (pointerful) data */
 #ifdef THREAD_LOCAL_ALLOC
   GC_INNER void * GC_core_malloc(size_t lb)
@@ -375,13 +411,13 @@ void * calloc(size_t n, size_t lb)
 # include <string.h>
   char *strdup(const char *s)
   {
-    size_t len = strlen(s) + 1;
-    char * result = ((char *)REDIRECT_MALLOC(len+1));
+    size_t lb = strlen(s) + 1;
+    char *result = (char *)REDIRECT_MALLOC(lb);
     if (result == 0) {
       errno = ENOMEM;
       return 0;
     }
-    BCOPY(s, result, len+1);
+    BCOPY(s, result, lb);
     return result;
   }
 #endif /* !defined(strdup) */
@@ -389,6 +425,26 @@ void * calloc(size_t n, size_t lb)
  /* and thus the right thing will happen even without overriding it.     */
  /* This seems to be true on most Linux systems.                         */
 
+#ifndef strndup
+  /* This is similar to strdup().       */
+# include <string.h>
+  char *strndup(const char *str, size_t size)
+  {
+    char *copy;
+    size_t len = strlen(str);
+    if (len > size)
+      len = size;
+    copy = (char *)REDIRECT_MALLOC(len + 1);
+    if (copy == NULL) {
+      errno = ENOMEM;
+      return NULL;
+    }
+    BCOPY(str, copy, len);
+    copy[len] = '\0';
+    return copy;
+  }
+#endif /* !strndup */
+
 #undef GC_debug_malloc_replacement
 
 # endif /* REDIRECT_MALLOC */
index b27c8b0..8d6939b 100644 (file)
--- a/mallocx.c
+++ b/mallocx.c
 
 #include <stdio.h>
 
+#ifdef MSWINCE
+# ifndef WIN32_LEAN_AND_MEAN
+#   define WIN32_LEAN_AND_MEAN 1
+# endif
+# define NOSERVICE
+# include <windows.h>
+#else
+# include <errno.h>
+#endif
+
 /* Some externally visible but unadvertised variables to allow access to */
 /* free lists from inlined allocators without including gc_priv.h        */
 /* or introducing dependencies on internal data structure layouts.       */
@@ -517,6 +527,28 @@ GC_API void * GC_CALL GC_memalign(size_t align, size_t lb)
     return result;
 }
 
+/* This one exists largerly to redirect posix_memalign for leaks finding. */
+GC_API int GC_CALL GC_posix_memalign(void **memptr, size_t align, size_t lb)
+{
+  /* Check alignment properly.  */
+  if (((align - 1) & align) != 0 || align < sizeof(void *)) {
+#   ifdef MSWINCE
+      return ERROR_INVALID_PARAMETER;
+#   else
+      return EINVAL;
+#   endif
+  }
+
+  if ((*memptr = GC_memalign(align, lb)) == NULL) {
+#   ifdef MSWINCE
+      return ERROR_NOT_ENOUGH_MEMORY;
+#   else
+      return ENOMEM;
+#   endif
+  }
+  return 0;
+}
+
 #ifdef ATOMIC_UNCOLLECTABLE
   /* Allocate lb bytes of pointerfree, untraced, uncollectable data     */
   /* This is normally roughly equivalent to the system malloc.          */
diff --git a/misc.c b/misc.c
index 0843bce..6533843 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -735,7 +735,6 @@ GC_API void GC_CALL GC_init(void)
 #   endif
     if (0 != GETENV("GC_FIND_LEAK")) {
       GC_find_leak = 1;
-      atexit(GC_exit_check);
     }
     if (0 != GETENV("GC_ALL_INTERIOR_POINTERS")) {
       GC_all_interior_pointers = 1;
@@ -990,6 +989,12 @@ GC_API void GC_CALL GC_init(void)
       }
 #   endif
 
+    if (GC_find_leak) {
+      /* This is to give us at least one chance to detect leaks.        */
+      /* This may report some very benign leaks, but ...                */
+      atexit(GC_exit_check);
+    }
+
     /* The rest of this again assumes we don't really hold      */
     /* the allocation lock.                                     */
 #   if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
index 53bc3b6..0ef0d22 100644 (file)
@@ -594,9 +594,9 @@ GC_INNER void GC_stop_world(void)
           __asm__ __volatile__ ("push %r15"); \
           __asm__ __volatile__ ("mov %%esp, %0" \
                     : "=m" (GC_nacl_gc_thread_self->stop_info.stack_ptr)); \
-          memcpy(GC_nacl_gc_thread_self->stop_info.reg_storage, \
-                 GC_nacl_gc_thread_self->stop_info.stack_ptr, \
-                 NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t)); \
+          BCOPY(GC_nacl_gc_thread_self->stop_info.stack_ptr, \
+                GC_nacl_gc_thread_self->stop_info.reg_storage, \
+                NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t)); \
           __asm__ __volatile__ ("naclasp $48, %r15"); \
         } while (0)
 # elif defined(__i386__)
@@ -608,9 +608,9 @@ GC_INNER void GC_stop_world(void)
           __asm__ __volatile__ ("push %edi"); \
           __asm__ __volatile__ ("mov %%esp, %0" \
                     : "=m" (GC_nacl_gc_thread_self->stop_info.stack_ptr)); \
-           memcpy(GC_nacl_gc_thread_self->stop_info.reg_storage, \
-                  GC_nacl_gc_thread_self->stop_info.stack_ptr, \
-                  NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t));\
+          BCOPY(GC_nacl_gc_thread_self->stop_info.stack_ptr, \
+                GC_nacl_gc_thread_self->stop_info.reg_storage, \
+                NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t));\
           __asm__ __volatile__ ("add $16, %esp"); \
         } while (0)
 # else
@@ -655,8 +655,8 @@ GC_INNER void GC_stop_world(void)
       GC_nacl_thread_parked[GC_nacl_thread_idx] = 0;
 
       /* Clear out the reg storage for next suspend.    */
-      memset(GC_nacl_gc_thread_self->stop_info.reg_storage, 0,
-             NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t));
+      BZERO(GC_nacl_gc_thread_self->stop_info.reg_storage,
+            NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t));
     }
   }
 
@@ -678,8 +678,8 @@ GC_INNER void GC_stop_world(void)
     int i;
     pthread_mutex_lock(&GC_nacl_thread_alloc_lock);
     if (!GC_nacl_thread_parking_inited) {
-      memset(GC_nacl_thread_parked, 0, sizeof(GC_nacl_thread_parked));
-      memset(GC_nacl_thread_used, 0, sizeof(GC_nacl_thread_used));
+      BZERO(GC_nacl_thread_parked, sizeof(GC_nacl_thread_parked));
+      BZERO(GC_nacl_thread_used, sizeof(GC_nacl_thread_used));
       GC_nacl_thread_parking_inited = TRUE;
     }
     GC_ASSERT(GC_nacl_num_gc_threads <= MAX_NACL_GC_THREADS);
index d592bba..68384bc 100644 (file)
@@ -241,7 +241,7 @@ GC_INNER unsigned long GC_lock_holder = NO_THREAD;
       if (NULL == dl_handle) {
         while (isdigit(libpthread_name[len-1])) --len;
         if (libpthread_name[len-1] == '.') --len;
-        memcpy(namebuf, libpthread_name, len);
+        BCOPY(libpthread_name, namebuf, len);
         namebuf[len] = '\0';
         dl_handle = dlopen(namebuf, RTLD_LAZY);
       }
index 99fc14c..1e07a38 100644 (file)
 
 #if defined(GC_WIN32_THREADS)
 
+#ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN 1
+#endif
+#define NOSERVICE
 #include <windows.h>
 
 #ifdef THREAD_LOCAL_ALLOC