📄 local_services.c
字号:
/*****************************************************************************/
/* Copyright 1998, Hewlett-Packard Company */
/* All rights reserved */
/* File: "local_services.c" */
/* Description: Abstracts platform and/or application dependent services, */
/* such as memory heap management, process termination and */
/* messaging. */
/* Author: David Taubman */
/* Affiliation: Hewlett-Packard and */
/* The University of New South Wales, Australia */
/* Version: VM6.0 */
/* Last Revised: 27 December, 1999 */
/*****************************************************************************/
/*****************************************************************************/
/* Modified by David Taubman to force the `local_malloc' function to zero */
/* the contents of all allocated memory. */
/*****************************************************************************/
#include <local_services.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
typedef
struct local_mem {
struct local_mem_stats *owner;
int num_bytes;
int id;
struct local_mem *next;
} local_mem, *local_mem_ptr;
/* This header is attached to every chunk of memory allocated by
`local_malloc'. Of course, this is a little wasteful, but the
purpose is to facilitate debugging and reporting and verification
of memory consumption throughout the system.
`owner' points to the `local_mem_stats' structure to whose list
this chunk of memory belongs.
`num_bytes' holds the number of bytes which were allocated, not
including the header.
`id' is a unique integer which is included to facilitate the
tracking and elimination of memory leaks. Every call to `local_malloc'
generates a different `id' (usually by simply incrementing a counter).
`next' is used to link all memory requests with the same key string
together. */
typedef
struct local_mem_stats {
const char *key;
local_mem_ptr head;
int total_bytes;
int current_bytes;
int peak_bytes;
struct local_mem_stats *next;
} local_mem_stats, *local_mem_stats_ptr;
/* This structure is used to build a list with one entry for each
key string with which memory is allocated by `local_malloc'.
`key' points to the string passed in to `local_malloc'.
`head' points to the head of a list of all memory chunks which
are currently allocated.
`total_bytes' holds the total number of bytes which have been
allocated with this key string, not taking into account the fact that
some of this memory may have been freed.
`current_bytes' holds the number of bytes which are currently
allocated.
`peak_bytes' holds the maximum number of bytes which have ever
been simultaneously allocated with this key string. */
static local_mem_stats_ptr mem_stats = NULL;
static int local_current_bytes = 0;
static int local_peak_bytes = 0;
static int local_next_id = 0;
static int local_stop_id = 0;
static int local_heap_already_started = 0;
/* ========================================================================= */
/* --------------------------- Heap Management ----------------------------- */
/* ========================================================================= */
/*****************************************************************************/
/* EXTERN local_memory_collect_stats */
/*****************************************************************************/
void
local_memory_collect_stats(void)
{
if (local_heap_already_started)
local_error("Attempting to invoke `local_memory_collect_stats' after "
"the first call to `local_malloc'!!");
local_next_id = 1;
}
/*****************************************************************************/
/* EXTERN local_memory_set_stop_id */
/*****************************************************************************/
void
local_memory_set_stop_id(int stop_id)
{
if ((local_next_id == 0) && (stop_id != 0))
local_error("Attempting to set a memory \"stop id\" without first "
"starting the statistics collection sub-system with a call "
"to `local_memory_collect_stats'!");
local_stop_id = stop_id;
}
/*****************************************************************************/
/* EXTERN local_malloc */
/*****************************************************************************/
void *
local_malloc(const char *key, int num_bytes)
{
local_mem_stats_ptr stats, scan, prev;
local_mem_ptr result;
int cmp = 0;
local_heap_already_started = 1;
if (local_next_id == 0)
{ /* No special features. */
void *ptr;
ptr = malloc((size_t) num_bytes);
if (ptr == NULL)
local_error("OUT OF MEMORY!! Heap exhausted while trying to "
"allocate a new memory block of size %d bytes!",num_bytes);
memset(ptr,0,(size_t) num_bytes);
return(ptr);
}
for (prev=NULL, scan=mem_stats; scan != NULL; prev=scan, scan=scan->next)
if ((cmp = strcmp(scan->key,key)) <= 0)
break;
if ((scan != NULL) && (cmp == 0))
stats = scan;
else
{
stats = (local_mem_stats_ptr) malloc(sizeof(local_mem_stats));
if (stats == NULL)
local_error("OUT OF MEMORY!! Heap exhausted while trying to "
"allocate a new memory block of size %d bytes!",num_bytes);
memset(stats,0,sizeof(local_mem_stats));
stats->next = scan;
if (prev == NULL)
mem_stats = stats;
else
prev->next = stats;
stats->key = key;
}
result = (local_mem_ptr) malloc(sizeof(local_mem)+(size_t) num_bytes);
if (result == NULL)
local_error("OUT OF MEMORY!! Heap exhausted while trying to "
"allocate a new memory block of size %d bytes!",num_bytes);
if (local_next_id == local_stop_id)
{ /* Stop here to catch memory leaks. */
assert(0);
}
result->id = local_next_id++;
result->num_bytes = num_bytes;
result->owner = stats;
result->next = stats->head;
stats->head = result;
stats->total_bytes += num_bytes;
stats->current_bytes += num_bytes;
if (stats->current_bytes > stats->peak_bytes)
stats->peak_bytes = stats->current_bytes;
local_current_bytes += num_bytes;
if (local_current_bytes > local_peak_bytes)
local_peak_bytes = local_current_bytes;
memset((void *)(result+1),0,(size_t) num_bytes);
return((void *)(result+1));
}
/*****************************************************************************/
/* EXTERN local_realloc */
/*****************************************************************************/
void *
local_realloc(void *ptr, int num_bytes)
{
local_mem_ptr head, new_head;
local_mem_stats_ptr stats;
int change;
if (ptr == NULL)
local_error("NULL pointer supplied to `local_realloc'!!");
if (local_next_id == 0)
{ /* No special features. */
ptr = realloc(ptr,(size_t) num_bytes);
return(ptr);
}
head = ((local_mem_ptr) ptr) - 1;
stats = head->owner;
assert(stats != NULL);
new_head = (local_mem_ptr)
realloc(head,sizeof(local_mem)+(size_t) num_bytes);
if (new_head != head)
{
local_mem_ptr scan, prev;
for (prev=NULL, scan=stats->head;
scan != NULL; prev=scan, scan=scan->next)
if (scan == head)
break;
if (scan == NULL)
local_error("Attempting to realloc a chunk of memory which was not "
"allocated using `local_malloc' or which has been "
"corrupted!");
if (prev != NULL)
prev->next = new_head;
else
stats->head = new_head;
head = new_head;
}
change = num_bytes - head->num_bytes;
head->num_bytes = num_bytes;
stats->current_bytes += change;
local_current_bytes += change;
if (change > 0)
{
stats->total_bytes += change;
if (stats->current_bytes > stats->peak_bytes)
stats->peak_bytes = stats->current_bytes;
if (local_current_bytes > local_peak_bytes)
local_peak_bytes = local_current_bytes;
}
return((void *)(head+1));
}
/*****************************************************************************/
/* EXTERN local_free */
/*****************************************************************************/
void
local_free(void *ptr)
{
local_mem_ptr head, prev, scan;
local_mem_stats_ptr stats;
if (ptr == NULL)
local_error("Attempting to deallocate memory via a NULL pointer!");
if (local_next_id == 0)
{ /* No special features. */
free(ptr);
return;
}
head = ((local_mem_ptr) ptr) - 1;
stats = head->owner;
assert(stats != NULL);
for (prev=NULL, scan=stats->head;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -