You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
289 lines
7.8 KiB
289 lines
7.8 KiB
/*
|
|
* Copyright(C) 1999-2020 National Technology & Engineering Solutions
|
|
* of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with
|
|
* NTESS, the U.S. Government retains certain rights in this software.
|
|
*
|
|
* See packages/seacas/LICENSE for details
|
|
*/
|
|
|
|
#include <stddef.h> // for size_t
|
|
#include <stdio.h> // for NULL, fprintf, printf, FILE, etc
|
|
#include <stdlib.h> // for malloc, free, realloc
|
|
|
|
static int nmalloc = 0; /* number of calls to malloc */
|
|
static int nfree = 0; /* number of calls to free */
|
|
static size_t bytes_used = 0; /* current dynamic memory usage */
|
|
static size_t bytes_max = 0; /* largest dynamic memory usage */
|
|
|
|
static struct smalloc_debug_data
|
|
{
|
|
int order; /* which smalloc call is it? */
|
|
size_t size; /* size of malloc invocation */
|
|
double * ptr; /* memory location returned */
|
|
struct smalloc_debug_data *next; /* pointer to next element */
|
|
} *top = NULL;
|
|
|
|
void message(char *msg, size_t n, FILE *ofile)
|
|
{
|
|
fprintf(stderr, msg, n);
|
|
if (ofile != NULL) {
|
|
fprintf(ofile, msg, n);
|
|
}
|
|
}
|
|
|
|
void sfree(void *ptr);
|
|
|
|
/* Safe version of malloc. Does not initialize memory .*/
|
|
void *smalloc(size_t n)
|
|
{
|
|
extern FILE *Output_File; /* output file or null */
|
|
extern int DEBUG_MEMORY; /* use debug memory allocator? */
|
|
void * ptr; /* return value */
|
|
struct smalloc_debug_data *new; /* data structure for malloc data */
|
|
void bail(char *msg, int status);
|
|
|
|
nmalloc++;
|
|
if (n == 0) {
|
|
message("ERROR: Non-positive argument to smalloc (%zu).\n", n, Output_File);
|
|
bail(NULL, 1);
|
|
}
|
|
|
|
ptr = malloc(n);
|
|
|
|
if (ptr == NULL) {
|
|
message("Program out of space while attempting to allocate %zu.\n", n, Output_File);
|
|
bail(NULL, 1);
|
|
}
|
|
|
|
if (DEBUG_MEMORY > 1) {
|
|
new = (struct smalloc_debug_data *)malloc(sizeof(struct smalloc_debug_data));
|
|
|
|
if (new == NULL) {
|
|
message("WARNING: No space for malloc_debug %zu.\n", n, Output_File);
|
|
return (ptr);
|
|
}
|
|
|
|
new->order = nmalloc;
|
|
new->size = n;
|
|
new->ptr = ptr;
|
|
new->next = top;
|
|
top = new;
|
|
bytes_used += n;
|
|
if (bytes_used > bytes_max) {
|
|
bytes_max = bytes_used;
|
|
}
|
|
}
|
|
|
|
if (DEBUG_MEMORY > 2) {
|
|
printf(" order=%d, size=%zu, location=%p\n", nmalloc, n, ptr);
|
|
}
|
|
|
|
return (ptr);
|
|
}
|
|
|
|
/* Safe version of malloc. Does not initialize memory .*/
|
|
/* Returns instead of dying if it fails. */
|
|
void *smalloc_ret(size_t n)
|
|
{
|
|
extern FILE *Output_File; /* output file or null */
|
|
extern int DEBUG_MEMORY; /* use debug memory allocator? */
|
|
void * ptr; /* return value */
|
|
struct smalloc_debug_data *new; /* data structure for malloc data */
|
|
void bail(char *msg, int status);
|
|
|
|
ptr = NULL;
|
|
if (n == 0) {
|
|
message("ERROR: Non-positive argument to smalloc_ret (%zu).\n", n, Output_File);
|
|
bail(NULL, 1);
|
|
}
|
|
|
|
else {
|
|
nmalloc++;
|
|
ptr = malloc(n);
|
|
|
|
if (ptr == NULL) {
|
|
nmalloc--;
|
|
message("\nERROR: Unable to allocate %zu bytes of memory.\n", n, Output_File);
|
|
}
|
|
else {
|
|
|
|
if (DEBUG_MEMORY > 1) {
|
|
new = (struct smalloc_debug_data *)malloc(sizeof(struct smalloc_debug_data));
|
|
|
|
if (new == NULL) {
|
|
message("WARNING: No space for malloc_debug %zu.\n", n, Output_File);
|
|
return (ptr);
|
|
}
|
|
|
|
new->order = nmalloc;
|
|
new->size = n;
|
|
new->ptr = ptr;
|
|
new->next = top;
|
|
top = new;
|
|
bytes_used += n;
|
|
if (bytes_used > bytes_max) {
|
|
bytes_max = bytes_used;
|
|
}
|
|
}
|
|
|
|
if (DEBUG_MEMORY > 2) {
|
|
printf(" order=%d, size=%zu, location=%p\n", nmalloc, n, ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (ptr);
|
|
}
|
|
|
|
/* Safe version of realloc */
|
|
void *srealloc(void *ptr, size_t n)
|
|
{
|
|
extern FILE * Output_File; /* output file or null */
|
|
void * p; /* returned pointer */
|
|
extern int DEBUG_MEMORY; /* use debug memory allocator? */
|
|
struct smalloc_debug_data *dbptr; /* loops through debug list */
|
|
void bail(char *msg, int status);
|
|
|
|
if (ptr == NULL) {
|
|
if (n == 0) {
|
|
return (NULL);
|
|
}
|
|
|
|
p = smalloc(n);
|
|
}
|
|
else {
|
|
if (n == 0) {
|
|
sfree(ptr);
|
|
return (NULL);
|
|
}
|
|
|
|
p = realloc(ptr, n);
|
|
if (DEBUG_MEMORY > 1) {
|
|
for (dbptr = top; dbptr != NULL && dbptr->ptr != ptr; dbptr = dbptr->next) {
|
|
;
|
|
}
|
|
if (dbptr == NULL) {
|
|
fprintf(stderr, "Memory error: In srealloc, address not found in debug list (%p)\n", ptr);
|
|
}
|
|
else {
|
|
dbptr->size = n;
|
|
dbptr->ptr = p;
|
|
bytes_used += n;
|
|
if (bytes_used > bytes_max) {
|
|
bytes_max = bytes_used;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (p == NULL) {
|
|
message("Program out of space while attempting to reallocate %zu.\n", n, Output_File);
|
|
bail(NULL, 1);
|
|
}
|
|
return (p);
|
|
}
|
|
|
|
/* Safe version of realloc */
|
|
/* Returns instead of dying if it fails. */
|
|
void *srealloc_ret(void *ptr, size_t n)
|
|
{
|
|
extern FILE * Output_File; /* output file or null */
|
|
void * p; /* returned pointer */
|
|
extern int DEBUG_MEMORY; /* use debug memory allocator? */
|
|
struct smalloc_debug_data *dbptr; /* loops through debug list */
|
|
|
|
if (ptr == NULL) {
|
|
if (n == 0) {
|
|
return (NULL);
|
|
}
|
|
|
|
p = smalloc(n);
|
|
}
|
|
else {
|
|
if (n == 0) {
|
|
sfree(ptr);
|
|
return (NULL);
|
|
}
|
|
|
|
p = realloc(ptr, n);
|
|
if (DEBUG_MEMORY > 1) {
|
|
for (dbptr = top; dbptr != NULL && dbptr->ptr != ptr; dbptr = dbptr->next) {
|
|
;
|
|
}
|
|
if (dbptr == NULL) {
|
|
fprintf(stderr, "Memory error: In srealloc_ret, address not found in debug list (%p)\n",
|
|
ptr);
|
|
}
|
|
else {
|
|
dbptr->size = n;
|
|
dbptr->ptr = p;
|
|
bytes_used += n;
|
|
if (bytes_used > bytes_max) {
|
|
bytes_max = bytes_used;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (p == NULL && DEBUG_MEMORY > 0) {
|
|
message("WARNING: Program out of space while attempting to reallocate %zu.\n", n, Output_File);
|
|
}
|
|
return (p);
|
|
}
|
|
|
|
/* Safe version of free. */
|
|
void sfree(void *ptr)
|
|
{
|
|
extern FILE * Output_File; /* output file or null */
|
|
extern int DEBUG_MEMORY; /* use debug memory allocator? */
|
|
struct smalloc_debug_data * dbptr; /* loops through debug list */
|
|
struct smalloc_debug_data **prev; /* holds previous pointer */
|
|
|
|
if (DEBUG_MEMORY > 1) {
|
|
if (ptr != NULL) { /* search through debug list for it */
|
|
prev = ⊤
|
|
for (dbptr = top; dbptr != NULL && dbptr->ptr != ptr; dbptr = dbptr->next) {
|
|
prev = &(dbptr->next);
|
|
}
|
|
if (dbptr == NULL) {
|
|
fprintf(stderr, "Memory error: In sfree, address not found in debug list (%p)\n", ptr);
|
|
if (Output_File != NULL) {
|
|
fprintf(Output_File, "Memory error: In sfree, address not found in debug list (%p)\n",
|
|
ptr);
|
|
}
|
|
}
|
|
else {
|
|
*prev = dbptr->next;
|
|
bytes_used -= dbptr->size;
|
|
free(dbptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ptr != NULL) {
|
|
nfree++;
|
|
free(ptr);
|
|
}
|
|
}
|
|
|
|
void smalloc_stats(void)
|
|
{
|
|
extern int DEBUG_MEMORY; /* use debug memory allocator? */
|
|
struct smalloc_debug_data *dbptr; /* loops through debug list */
|
|
|
|
if (DEBUG_MEMORY == 1) {
|
|
printf("Calls to smalloc = %d, Calls to sfree = %d\n", nmalloc, nfree);
|
|
}
|
|
if (DEBUG_MEMORY > 1) {
|
|
printf("Calls to smalloc = %d, Calls to sfree = %d, maximum bytes = %zu\n", nmalloc, nfree,
|
|
bytes_max);
|
|
if (top != NULL) {
|
|
printf("Remaining allocations:\n");
|
|
for (dbptr = top; dbptr != NULL; dbptr = dbptr->next) {
|
|
printf(" order=%d, size=%zu, location=%p\n", dbptr->order, dbptr->size, (void *)dbptr->ptr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int smalloc_num(void) { return (nmalloc); }
|
|
|