You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
4.6 KiB
C
166 lines
4.6 KiB
C
/* $Id: xmalloc.c 5381 2002-03-31 22:35:47Z rra $
|
|
**
|
|
** malloc routines with failure handling.
|
|
**
|
|
** Usage:
|
|
**
|
|
** extern xmalloc_handler_t memory_error;
|
|
** extern const char *string;
|
|
** char *buffer;
|
|
**
|
|
** xmalloc_error_handler = memory_error;
|
|
** buffer = xmalloc(1024);
|
|
** xrealloc(buffer, 2048);
|
|
** free(buffer);
|
|
** buffer = xcalloc(1024);
|
|
** free(buffer);
|
|
** buffer = xstrdup(string);
|
|
** free(buffer);
|
|
** buffer = xstrndup(string, 25);
|
|
**
|
|
** xmalloc, xcalloc, xrealloc, and xstrdup behave exactly like their C
|
|
** library counterparts without the leading x except that they will never
|
|
** return NULL. Instead, on error, they call xmalloc_error_handler,
|
|
** passing it the name of the function whose memory allocation failed, the
|
|
** amount of the allocation, and the file and line number where the
|
|
** allocation function was invoked (from __FILE__ and __LINE__). This
|
|
** function may do whatever it wishes, such as some action to free up
|
|
** memory or a call to sleep to hope that system resources return. If the
|
|
** handler returns, the interrupted memory allocation function will try its
|
|
** allocation again (calling the handler again if it still fails).
|
|
**
|
|
** xstrndup behaves like xstrdup but only copies the given number of
|
|
** characters. It allocates an additional byte over its second argument and
|
|
** always nul-terminates the string.
|
|
**
|
|
** The default error handler, if none is set by the caller, prints an error
|
|
** message to stderr and exits with exit status 1. An error handler must
|
|
** take a const char * (function name), size_t (bytes allocated), const
|
|
** char * (file), and int (line).
|
|
**
|
|
** xmalloc will return a pointer to a valid memory region on an xmalloc of 0
|
|
** bytes, ensuring this by allocating space for one character instead of 0
|
|
** bytes.
|
|
**
|
|
** The functions defined here are actually x_malloc, x_realloc, etc. The
|
|
** header file defines macros named xmalloc, etc. that pass the file name
|
|
** and line number to these functions.
|
|
*/
|
|
|
|
/* Used for unused parameters to silence gcc warnings. */
|
|
#define UNUSED __attribute__((__unused__))
|
|
|
|
/* Make available the bool type. */
|
|
#if INN_HAVE_STDBOOL_H
|
|
# include <stdbool.h>
|
|
#else
|
|
# undef true
|
|
# undef false
|
|
# define true (1)
|
|
# define false (0)
|
|
# ifndef __cplusplus
|
|
# define bool int
|
|
# endif
|
|
#endif /* INN_HAVE_STDBOOL_H */
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <crypt.h>
|
|
#include <fcntl.h>
|
|
#include <pwd.h>
|
|
#include <grp.h>
|
|
|
|
#include "messages.h"
|
|
|
|
/* Failure handler takes the function, the size, the file, and the line. */
|
|
typedef void (*xmalloc_handler_t)(const char *, size_t, const char *, int);
|
|
|
|
/* Assign to this variable to choose a handler other than the default, which
|
|
just calls sysdie. */
|
|
extern xmalloc_handler_t xmalloc_error_handler;
|
|
|
|
/* The default error handler. */
|
|
void
|
|
xmalloc_fail(const char *function, size_t size, const char *file, int line)
|
|
{
|
|
sysdie("failed to %s %lu bytes at %s line %d", function,
|
|
(unsigned long) size, file, line);
|
|
}
|
|
|
|
/* Assign to this variable to choose a handler other than the default. */
|
|
xmalloc_handler_t xmalloc_error_handler = xmalloc_fail;
|
|
|
|
void *
|
|
x_malloc(size_t size, const char *file, int line)
|
|
{
|
|
void *p;
|
|
size_t real_size;
|
|
|
|
real_size = (size > 0) ? size : 1;
|
|
p = malloc(real_size);
|
|
while (p == NULL) {
|
|
(*xmalloc_error_handler)("malloc", size, file, line);
|
|
p = malloc(real_size);
|
|
}
|
|
return p;
|
|
}
|
|
|
|
void *
|
|
x_calloc(size_t n, size_t size, const char *file, int line)
|
|
{
|
|
void *p;
|
|
|
|
n = (n > 0) ? n : 1;
|
|
size = (size > 0) ? size : 1;
|
|
p = calloc(n, size);
|
|
while (p == NULL) {
|
|
(*xmalloc_error_handler)("calloc", n * size, file, line);
|
|
p = calloc(n, size);
|
|
}
|
|
return p;
|
|
}
|
|
|
|
void *
|
|
x_realloc(void *p, size_t size, const char *file, int line)
|
|
{
|
|
void *newp;
|
|
|
|
newp = realloc(p, size);
|
|
while (newp == NULL && size > 0) {
|
|
(*xmalloc_error_handler)("realloc", size, file, line);
|
|
newp = realloc(p, size);
|
|
}
|
|
return newp;
|
|
}
|
|
|
|
char *
|
|
x_strdup(const char *s, const char *file, int line)
|
|
{
|
|
char *p;
|
|
size_t len;
|
|
|
|
len = strlen(s) + 1;
|
|
p = malloc(len);
|
|
while (p == NULL) {
|
|
(*xmalloc_error_handler)("strdup", len, file, line);
|
|
p = malloc(len);
|
|
}
|
|
memcpy(p, s, len);
|
|
return p;
|
|
}
|
|
|
|
char *
|
|
x_strndup(const char *s, size_t size, const char *file, int line)
|
|
{
|
|
char *p;
|
|
|
|
p = malloc(size + 1);
|
|
while (p == NULL) {
|
|
(*xmalloc_error_handler)("strndup", size + 1, file, line);
|
|
p = malloc(size + 1);
|
|
}
|
|
memcpy(p, s, size);
|
|
p[size] = '\0';
|
|
return p;
|
|
}
|