File: safe.c

package info (click to toggle)
elvis 2.2.0-10
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 6,632 kB
  • ctags: 18,477
  • sloc: ansic: 94,727; sh: 1,357; makefile: 425
file content (205 lines) | stat: -rw-r--r-- 4,976 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/* safe.c */
/* Copyright 1995 by Steve Kirkendall */


#include "elvis.h"
#ifdef FEATURE_RCSID
char id_safe[] = "$Id: safe.c,v 2.17 2003/10/17 17:41:23 steve Exp $";
#endif

#ifndef DEBUG_ALLOC
void *safealloc(qty, size)
	int	qty;	/* number of items to allocate */
	size_t	size;	/* size of each item */
{
	void	*newp;

	newp = (void *)calloc((size_t)qty, size);
	if (!newp)
	{
		msg(MSG_FATAL, "no memory");
	}
	return newp;
}

void safefree(ptr)
	void	*ptr;	/* pointer to item(s) to be freed */
{
	free(ptr);
}

char *safedup(str)
	char	*str;	/* nul-terminated string to be duplicated */
{
	char *newp = (char *)safealloc((int)strlen(str) + 1, sizeof(char));
	strcpy(newp, str);
	return newp;
}
#else

#define MAGIC1 0x10d934a2
#define MAGIC2 0x42df3219
typedef struct sainfo_s
{
	struct sainfo_s *next;	/* another allocated memory chunk */
	char		*file;	/* source file where allocated */
	int		line;	/* source line where allocated */
	int		size;	/* number of longs allocated */
	ELVBOOL		kept;	/* if ElvTrue, don't complain if never freed */
	long		magic[2];/* magic number plus application info */
} sainfo_t;

sainfo_t *allocated;
	
/* inspect the list of allocated memory */
void safeinspect()
{
	sainfo_t	*scan;

	/* inspect list of allocated blocks for overflow/underflow */
	for (scan = allocated; scan; scan = scan->next)
	{
		if (scan->magic[0] != MAGIC1)
		{
			fprintf(stderr, "underflow in memory at 0x%lx, allocated from %s:%d, magic[0]=0x%lx\n",
				(long)scan, scan->file, scan->line, scan->magic[0]);
			abort();
		}
		else if (scan->magic[scan->size + 1] != MAGIC2)
		{
			fprintf(stderr, "overflow in memory at 0x%lx, allocated from %s:%d, magic[%d]=0x%lx\n",
				(long)scan, scan->file, scan->line, scan->size+1, scan->magic[scan->size + 1]);
			abort();
		}
	}
}


/* allocate memory, and remember where it was allocated */
void *_safealloc(file, line, kept, qty, size)
	char	*file;	/* name of source file where this func was called */
	int	line;	/* line of source file where this func was called */
	ELVBOOL	kept;	/* if ElvTrue, don't complain if never allocated */
	int	qty;	/* number of items to allocate */
	size_t	size;	/* size of each item */
{
	int	nlongs;
	sainfo_t *newp, *scan, *lag;

	/* inspect previous allocations */
	safeinspect();

	/* round user request up to whole number of longs */
	nlongs = (qty * size + sizeof(long) - 1) / sizeof(long);
	assert(nlongs * sizeof(long) >= qty * size);

	/* allocate storage space */
	newp = (sainfo_t *)calloc(1, sizeof(sainfo_t) + nlongs * sizeof(long));
	if (!newp)
	{
		msg(MSG_FATAL, "no memory");
	}

	/* save info about allocated memory */
	newp->file = file;
	newp->line = line;
	newp->size = nlongs;
	newp->kept = kept;
	newp->magic[0] = MAGIC1;
	newp->magic[1 + newp->size] = MAGIC2;
	for (scan = allocated, lag = NULL;
	     scan && (strcmp(file, scan->file) < 0 || (!strcmp(file, scan->file) && line < scan->line));
	     lag = scan, scan = scan->next)
	{
	}
	newp->next = scan;
	if (lag)
		lag->next = newp;
	else
		allocated = newp;

	/* count allocations from that spot */
	for (nlongs = 0, scan = newp;
	     scan && !strcmp(file, scan->file) && line == scan->line;
	     nlongs++, scan = scan->next)
	{
	}
	if (nlongs > 100 && (!kept || strcmp(file, "options.c")))
	{
		fprintf(stderr, "%d allocations from %s(%d)\n", nlongs, file, line);
	}

	/* return the application portion of allocated memory */
	return (void *)&newp->magic[1];
}


/* free allocated memory */
void _safefree(file, line, mem)
	char	*file;	/* name of source file where this func was called */
	int	line;	/* line of source file where this func was called */
	void	*mem;	/* item(s) to be freed */
{
	sainfo_t *scan, *lag;

	/* inspect previous allocations */
	safeinspect();

	/* locate the memory in the allocated list */
	for (lag = NULL, scan = allocated;
	     scan && (void *)&scan->magic[1] != mem;
	     lag = scan, scan = scan->next)
	{
	}

	/* if not in allocation list, fail */
	if (!scan)
	{
		fprintf(stderr, "attempt to free unallocated memory from %s:%ld\n",
			file, (long)line);
		return;
	}

	/* delete the memory from the allocated list */
	if (lag)
	{
		lag->next = scan->next;
	}
	else
	{
		allocated = scan->next;
	}

	/* free the memory */
	free(scan);
}

/* allocate a duplicate of a string, using _safealloc() */
char *_safedup(file, line, kept, str)
	char	*file;	/* name of source file where this func was called */
	int	line;	/* line of source file where this func was called */
	ELVBOOL	kept;	/* if ElvTrue, don't complain if never freed */
	char	*str;	/* nul-terminated string to duplicate */
{
	char	*newp;

	newp = (char *)_safealloc(file, line, kept, (int)(strlen(str) + 1), sizeof(char));
	strcpy(newp, str);
	return newp;
}

/* list any unfreed memory */
void safeterm()
{
	sainfo_t *scan;

	for (scan = allocated; scan; scan = scan->next)
	{
		if (!scan->kept)
		{
			fprintf(stderr, "memory allocated from %s:%ld never freed\n",
				scan->file, (long)scan->line);
		}
	}
}
#endif