Exemple #1
0
/**
 * Allocates the given number of bytes, as with standard malloc(), but
 * all bytes are initialized to zero as with calloc(). Guaranteed to
 * return #NULL if bytes is zero on all platforms. Returns #NULL if the
 * allocation fails.  The memory must be released with dbus_free().
 *
 * dbus_malloc0() memory is NOT safe to free with regular free() from
 * the C library. Free it with dbus_free() only.
 *
 * @param bytes number of bytes to allocate
 * @return allocated memory, or #NULL if the allocation fails.
 */
void*
dbus_malloc0 (size_t bytes)
{
#ifdef DBUS_BUILD_TESTS
  _dbus_initialize_malloc_debug ();
  
  if (_dbus_decrement_fail_alloc_counter ())
    {
      _dbus_verbose (" FAILING malloc0 of %ld bytes\n", (long) bytes);
      
      return NULL;
    }
#endif
  
  if (bytes == 0)
    return NULL;
#ifdef DBUS_BUILD_TESTS
  else if (fail_size != 0 && bytes > fail_size)
    return NULL;
  else if (guards)
    {
      void *block;

      block = calloc (bytes + GUARD_EXTRA_SIZE, 1);

      if (block)
        {
          _dbus_atomic_inc (&n_blocks_outstanding);
        }
      else if (malloc_cannot_fail)
        {
          _dbus_warn ("out of memory: calloc (%ld + %ld, 1)\n",
              (long) bytes, (long) GUARD_EXTRA_SIZE);
          _dbus_abort ();
        }

      return set_guards (block, bytes, SOURCE_MALLOC_ZERO);
    }
#endif
  else
    {
      void *mem;
      mem = calloc (bytes, 1);

#ifdef DBUS_BUILD_TESTS
      if (mem)
        {
          _dbus_atomic_inc (&n_blocks_outstanding);
        }
      else if (malloc_cannot_fail)
        {
          _dbus_warn ("out of memory: calloc (%ld)\n", (long) bytes);
          _dbus_abort ();
        }
#endif

      return mem;
    }
}
Exemple #2
0
/**
 * Allocates the given number of bytes, as with standard
 * malloc(). Guaranteed to return #NULL if bytes is zero
 * on all platforms. Returns #NULL if the allocation fails.
 * The memory must be released with dbus_free().
 *
 * dbus_malloc() memory is NOT safe to free with regular free() from
 * the C library. Free it with dbus_free() only.
 *
 * @param bytes number of bytes to allocate
 * @return allocated memory, or #NULL if the allocation fails.
 */
void*
dbus_malloc (size_t bytes)
{
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
    _dbus_initialize_malloc_debug ();

    if (_dbus_decrement_fail_alloc_counter ())
    {
        _dbus_verbose (" FAILING malloc of %ld bytes\n", (long) bytes);
        return NULL;
    }
#endif

    if (bytes == 0) /* some system mallocs handle this, some don't */
        return NULL;
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
    else if (fail_size != 0 && bytes > fail_size)
        return NULL;
    else if (guards)
    {
        void *block;

        block = malloc (bytes + GUARD_EXTRA_SIZE);
        if (block)
        {
            _dbus_atomic_inc (&n_blocks_outstanding);
        }
        else if (malloc_cannot_fail)
        {
            _dbus_warn ("out of memory: malloc (%ld + %ld)\n",
                        (long) bytes, (long) GUARD_EXTRA_SIZE);
            _dbus_abort ();
        }

        return set_guards (block, bytes, SOURCE_MALLOC);
    }
#endif
    else
    {
        void *mem;
        mem = malloc (bytes);

#ifdef DBUS_ENABLE_EMBEDDED_TESTS
        if (mem)
        {
            _dbus_atomic_inc (&n_blocks_outstanding);
        }
        else if (malloc_cannot_fail)
        {
            _dbus_warn ("out of memory: malloc (%ld)\n", (long) bytes);
            _dbus_abort ();
        }
#endif

        return mem;
    }
}
/**
 * Allocates the given number of bytes, as with standard
 * malloc(). Guaranteed to return #NULL if bytes is zero
 * on all platforms. Returns #NULL if the allocation fails.
 * The memory must be released with dbus_free().
 *
 * @param bytes number of bytes to allocate
 * @return allocated memory, or #NULL if the allocation fails.
 */
void*
dbus_malloc (size_t bytes)
{
#ifdef DBUS_BUILD_TESTS
  _dbus_initialize_malloc_debug ();
  
  if (_dbus_decrement_fail_alloc_counter ())
    {
      _dbus_verbose (" FAILING malloc of %ld bytes\n", (long) bytes);
      
      return NULL;
    }
#endif
  
  if (bytes == 0) /* some system mallocs handle this, some don't */
    return NULL;
#ifdef DBUS_BUILD_TESTS
  else if (fail_size != 0 && bytes > fail_size)
    return NULL;
  else if (guards)
    {
      void *block;

      block = malloc (bytes + GUARD_EXTRA_SIZE);
      if (block)
        n_blocks_outstanding += 1;
      
      return set_guards (block, bytes, SOURCE_MALLOC);
    }
#endif
  else
    {
      void *mem;
      mem = malloc (bytes);
#ifdef DBUS_BUILD_TESTS
      if (mem)
        n_blocks_outstanding += 1;
#endif
      return mem;
    }
}
Exemple #4
0
/**
 * Resizes a block of memory previously allocated by dbus_malloc() or
 * dbus_malloc0(). Guaranteed to free the memory and return #NULL if bytes
 * is zero on all platforms. Returns #NULL if the resize fails.
 * If the resize fails, the memory is not freed.
 *
 * @param memory block to be resized
 * @param bytes new size of the memory block
 * @return allocated memory, or #NULL if the resize fails.
 */
void*
dbus_realloc (void  *memory,
              size_t bytes)
{
#ifdef DBUS_BUILD_TESTS
  _dbus_initialize_malloc_debug ();
  
  if (_dbus_decrement_fail_alloc_counter ())
    {
      _dbus_verbose (" FAILING realloc of %ld bytes\n", (long) bytes);
      
      return NULL;
    }
#endif
  
  if (bytes == 0) /* guarantee this is safe */
    {
      dbus_free (memory);
      return NULL;
    }
#ifdef DBUS_BUILD_TESTS
  else if (fail_size != 0 && bytes > fail_size)
    return NULL;
  else if (guards)
    {
      if (memory)
        {
          size_t old_bytes;
          void *block;
          
          check_guards (memory, FALSE);
          
          block = realloc (((unsigned char*)memory) - GUARD_START_OFFSET,
                           bytes + GUARD_EXTRA_SIZE);

	  old_bytes = *(dbus_uint32_t*)block;
          if (block && bytes >= old_bytes)
            /* old guards shouldn't have moved */
            check_guards (((unsigned char*)block) + GUARD_START_OFFSET, FALSE);
          
          return set_guards (block, bytes, SOURCE_REALLOC);
        }
      else
        {
          void *block;
          
          block = malloc (bytes + GUARD_EXTRA_SIZE);

          if (block)
	    _dbus_atomic_inc (&n_blocks_outstanding);
          
          return set_guards (block, bytes, SOURCE_REALLOC_NULL);   
        }
    }
#endif
  else
    {
      void *mem;
      mem = realloc (memory, bytes);
#ifdef DBUS_BUILD_TESTS
      if (memory == NULL && mem != NULL)
	    _dbus_atomic_inc (&n_blocks_outstanding);
#endif
      return mem;
    }
}
Exemple #5
0
/**
 * Resizes a block of memory previously allocated by dbus_malloc() or
 * dbus_malloc0(). Guaranteed to free the memory and return #NULL if bytes
 * is zero on all platforms. Returns #NULL if the resize fails.
 * If the resize fails, the memory is not freed.
 *
 * @param memory block to be resized
 * @param bytes new size of the memory block
 * @return allocated memory, or #NULL if the resize fails.
 */
void*
_dbus_realloc (void  *memory,
               size_t bytes,
               const char *file,
               int line)
{
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
  _dbus_initialize_malloc_debug ();
  
  if (_dbus_decrement_fail_alloc_counter ())
    {
      _dbus_verbose (" FAILING realloc of %ld bytes\n", (long) bytes);
      
      return NULL;
    }
#endif
  
  if (bytes == 0) /* guarantee this is safe */
    {
      dbus_free (memory);
      return NULL;
    }
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
  else if (fail_size != 0 && bytes > fail_size)
    return NULL;
  else if (guards)
    {
      if (memory)
        {
          size_t old_bytes;
          void *block;
          
          check_guards (memory, FALSE);
          
          block = realloc (((unsigned char*)memory) - GUARD_START_OFFSET,
                           bytes + GUARD_EXTRA_SIZE);

          if (block == NULL)
            {
              if (malloc_cannot_fail)
                {
                  _dbus_warn ("out of memory: realloc (%p, %ld + %ld)\n",
                      memory, (long) bytes, (long) GUARD_EXTRA_SIZE);
                  _dbus_abort ();
                }

              return NULL;
            }
          dbus_track_free (((unsigned char*)memory) - GUARD_START_OFFSET);
          dbus_track_realloc (((unsigned char*)memory) - GUARD_START_OFFSET, bytes + GUARD_EXTRA_SIZE, file, line);

          old_bytes = *(dbus_uint32_t*)block;
          if (bytes >= old_bytes)
            /* old guards shouldn't have moved */
            check_guards (((unsigned char*)block) + GUARD_START_OFFSET, FALSE);
          
          return set_guards (block, bytes, SOURCE_REALLOC);
        }
      else
        {
          void *block;
          
          block = malloc (bytes + GUARD_EXTRA_SIZE);

          if (block)
            {
              _dbus_atomic_inc (&n_blocks_outstanding);
              dbus_track_malloc(block, bytes + GUARD_EXTRA_SIZE, file, line);
            }
          else if (malloc_cannot_fail)
            {
              _dbus_warn ("out of memory: malloc (%ld + %ld)\n",
                  (long) bytes, (long) GUARD_EXTRA_SIZE);
              _dbus_abort ();
            }

          return set_guards (block, bytes, SOURCE_REALLOC_NULL);   
        }
    }
#endif
  else
    {
      void *mem;
      mem = realloc (memory, bytes);

#ifdef DBUS_ENABLE_EMBEDDED_TESTS
      if (mem == NULL && malloc_cannot_fail)
        {
          _dbus_warn ("out of memory: malloc (%ld)\n", (long) bytes);
          _dbus_abort ();
        }

      if (memory == NULL && mem != NULL)
	    _dbus_atomic_inc (&n_blocks_outstanding);
#endif
      dbus_track_free (memory);
      dbus_track_realloc (mem, bytes, file, line);
      return mem;
    }
}
/**
 * Allocates an object from the memory pool.
 * The object must be freed with _dbus_mem_pool_dealloc().
 *
 * @param pool the memory pool
 * @returns the allocated object or #NULL if no memory.
 */
void*
_dbus_mem_pool_alloc (DBusMemPool *pool)
{
#ifdef DBUS_BUILD_TESTS
  if (_dbus_disable_mem_pools ())
    {
      DBusMemBlock *block;
      int alloc_size;
      
      /* This is obviously really silly, but it's
       * debug-mode-only code that is compiled out
       * when tests are disabled (_dbus_disable_mem_pools()
       * is a constant expression FALSE so this block
       * should vanish)
       */
      
      alloc_size = sizeof (DBusMemBlock) - ELEMENT_PADDING +
        pool->element_size;
      
      if (pool->zero_elements)
        block = dbus_malloc0 (alloc_size);
      else
        block = dbus_malloc (alloc_size);

      if (block != NULL)
        {
          block->next = pool->blocks;
          pool->blocks = block;
          pool->allocated_elements += 1;

          return (void*) &block->elements[0];
        }
      else
        return NULL;
    }
  else
#endif
    {
      if (_dbus_decrement_fail_alloc_counter ())
        {
          _dbus_verbose (" FAILING mempool alloc\n");
          return NULL;
        }
      else if (pool->free_elements)
        {
          DBusFreedElement *element = pool->free_elements;

          pool->free_elements = pool->free_elements->next;

          if (pool->zero_elements)
            memset (element, '\0', pool->element_size);

          pool->allocated_elements += 1;
          
          return element;
        }
      else
        {
          void *element;
      
          if (pool->blocks == NULL ||
              pool->blocks->used_so_far == pool->block_size)
            {
              /* Need a new block */
              DBusMemBlock *block;
              int alloc_size;
#ifdef DBUS_BUILD_TESTS
              int saved_counter;
#endif
          
              if (pool->block_size <= _DBUS_INT_MAX / 4) /* avoid overflow */
                {
                  /* use a larger block size for our next block */
                  pool->block_size *= 2;
                  _dbus_assert ((pool->block_size %
                                 pool->element_size) == 0);
                }

              alloc_size = sizeof (DBusMemBlock) - ELEMENT_PADDING + pool->block_size;

#ifdef DBUS_BUILD_TESTS
              /* We save/restore the counter, so that memory pools won't
               * cause a given function to have different number of
               * allocations on different invocations. i.e.  when testing
               * we want consistent alloc patterns. So we skip our
               * malloc here for purposes of failed alloc simulation.
               */
              saved_counter = _dbus_get_fail_alloc_counter ();
              _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
#endif
          
              if (pool->zero_elements)
                block = dbus_malloc0 (alloc_size);
              else
                block = dbus_malloc (alloc_size);

#ifdef DBUS_BUILD_TESTS
              _dbus_set_fail_alloc_counter (saved_counter);
              _dbus_assert (saved_counter == _dbus_get_fail_alloc_counter ());
#endif
          
              if (block == NULL)
                return NULL;

              block->used_so_far = 0;
              block->next = pool->blocks;
              pool->blocks = block;          
            }
      
          element = &pool->blocks->elements[pool->blocks->used_so_far];
          
          pool->blocks->used_so_far += pool->element_size;

          pool->allocated_elements += 1;
          
          return element;
        }
    }
}