Skip to content

Commit 3668b6e

Browse files
committed
Introduce xfree_sized and xrealloc_sized
1 parent 62c7300 commit 3668b6e

4 files changed

Lines changed: 148 additions & 4 deletions

File tree

Doxyfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ OUTPUT_DIRECTORY = doc
2424
JAVADOC_AUTOBRIEF = YES
2525
OPTIMIZE_OUTPUT_FOR_C = YES
2626
INPUT = src src/util include include/prism include/prism/util
27+
EXCLUDE = include/prism/debug_allocator.h
2728
HTML_OUTPUT = c
2829
SORT_MEMBER_DOCS = NO
2930
GENERATE_LATEX = NO

include/prism/debug_allocator.h

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/**
2+
* @file debug_allocator.h
3+
*
4+
* Decorate allocation function to ensure sizes are correct.
5+
*/
6+
#ifndef PRISM_DEBUG_ALLOCATOR_H
7+
#define PRISM_DEBUG_ALLOCATOR_H
8+
9+
#include <string.h>
10+
#include <stdio.h>
11+
#include <stdlib.h>
12+
13+
static inline void *
14+
pm_debug_malloc(size_t size)
15+
{
16+
size_t *memory = xmalloc(size + sizeof(size_t));
17+
memory[0] = size;
18+
return memory + 1;
19+
}
20+
21+
static inline void *
22+
pm_debug_calloc(size_t nmemb, size_t size)
23+
{
24+
size_t total_size = nmemb * size;
25+
void *ptr = pm_debug_malloc(total_size);
26+
memset(ptr, 0, total_size);
27+
return ptr;
28+
}
29+
30+
static inline void *
31+
pm_debug_realloc(void *ptr, size_t size)
32+
{
33+
if (ptr == NULL) {
34+
return pm_debug_malloc(size);
35+
}
36+
37+
size_t *memory = (size_t *)ptr;
38+
void *raw_memory = memory - 1;
39+
memory = (size_t *)xrealloc(raw_memory, size + sizeof(size_t));
40+
memory[0] = size;
41+
return memory + 1;
42+
}
43+
44+
static inline void
45+
pm_debug_free(void *ptr)
46+
{
47+
if (ptr != NULL) {
48+
size_t *memory = (size_t *)ptr;
49+
xfree(memory - 1);
50+
}
51+
}
52+
53+
static inline void
54+
pm_debug_free_sized(void *ptr, size_t old_size)
55+
{
56+
if (ptr != NULL) {
57+
size_t *memory = (size_t *)ptr;
58+
if (old_size != memory[-1]) {
59+
fprintf(stderr, "[BUG] buffer %p was allocated with size %lu but freed with size %lu\n", ptr, memory[-1], old_size);
60+
abort();
61+
}
62+
xfree_sized(memory - 1, old_size + sizeof(size_t));
63+
}
64+
}
65+
66+
static inline void *
67+
pm_debug_realloc_sized(void *ptr, size_t size, size_t old_size)
68+
{
69+
if (ptr == NULL) {
70+
if (old_size != 0) {
71+
fprintf(stderr, "[BUG] realloc_sized called with NULL pointer and old size %lu\n", old_size);
72+
abort();
73+
}
74+
return pm_debug_malloc(size);
75+
}
76+
77+
size_t *memory = (size_t *)ptr;
78+
if (old_size != memory[-1]) {
79+
fprintf(stderr, "[BUG] buffer %p was allocated with size %lu but realloced with size %lu\n", ptr, memory[-1], old_size);
80+
abort();
81+
}
82+
return pm_debug_realloc(ptr, size);
83+
}
84+
85+
#undef xmalloc
86+
#undef xrealloc
87+
#undef xcalloc
88+
#undef xfree
89+
#undef xrealloc_sized
90+
#undef xfree_sized
91+
92+
#define xmalloc pm_debug_malloc
93+
#define xrealloc pm_debug_realloc
94+
#define xcalloc pm_debug_calloc
95+
#define xfree pm_debug_free
96+
#define xrealloc_sized pm_debug_realloc_sized
97+
#define xfree_sized pm_debug_free_sized
98+
99+
#endif

include/prism/defines.h

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,12 @@
161161
* ```
162162
* #ifndef PRISM_XALLOCATOR_H
163163
* #define PRISM_XALLOCATOR_H
164-
* #define xmalloc my_malloc
165-
* #define xrealloc my_realloc
166-
* #define xcalloc my_calloc
167-
* #define xfree my_free
164+
* #define xmalloc my_malloc
165+
* #define xrealloc my_realloc
166+
* #define xcalloc my_calloc
167+
* #define xfree my_free
168+
* #define xrealloc_sized my_realloc_sized // (optional)
169+
* #define xfree_sized my_free_sized // (optional)
168170
* #endif
169171
* ```
170172
*/
@@ -204,6 +206,47 @@
204206
#endif
205207
#endif
206208

209+
#ifndef xfree_sized
210+
/**
211+
* The free_sized function that should be used. This can be overridden with the
212+
* PRISM_XALLOCATOR define.
213+
* If not defined, defaults to calling xfree.
214+
*/
215+
#define xfree_sized(p, s) xfree(p)
216+
#endif
217+
218+
/**
219+
* Convenience macro to call xfree_sized with a pointer to a fixed size object.
220+
* Example:
221+
* pm_call_node_t *target = xmalloc(sizeof(pm_call_node_t));
222+
* ...
223+
* PM_FREE_SIZED(target);
224+
*/
225+
#define PM_FREE_SIZED(p) xfree_sized((p), (sizeof(*(p))))
226+
227+
/**
228+
* Convenience macro to call xfree_sized with a pointer to an array of fixed size objects.
229+
* Example:
230+
* size_t capacity = 12;
231+
* pm_call_node_t *targets = xcalloc(capacity, sizeof(pm_call_node_t));
232+
* ...
233+
* PM_FREE_SIZED_N(target, capacity);
234+
*/
235+
#define PM_FREE_SIZED_N(p, n) xfree_sized((p), (sizeof(*(p))) * n)
236+
237+
#ifndef xrealloc_sized
238+
/**
239+
* The xrealloc_sized function that should be used. This can be overridden with the
240+
* PRISM_XALLOCATOR define.
241+
* If not defined, defaults to calling xrealloc.
242+
*/
243+
#define xrealloc_sized(p, ns, os) xrealloc(p, ns)
244+
#endif
245+
246+
#ifdef PRISM_BUILD_DEBUG
247+
#include "prism/debug_allocator.h"
248+
#endif
249+
207250
/**
208251
* If PRISM_BUILD_MINIMAL is defined, then we're going to define every possible
209252
* switch that will turn off certain features of prism.

prism.gemspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Gem::Specification.new do |spec|
4747
"ext/prism/extension.h",
4848
"include/prism.h",
4949
"include/prism/ast.h",
50+
"include/prism/debug_allocator.h",
5051
"include/prism/defines.h",
5152
"include/prism/diagnostic.h",
5253
"include/prism/encoding.h",

0 commit comments

Comments
 (0)