oj 3.14.1 → 3.14.2

Sign up to get free protection for your applications and to get access to all the features.
data/ext/oj/mem.c ADDED
@@ -0,0 +1,324 @@
1
+ // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
+
3
+ #include <pthread.h>
4
+ #include <stdbool.h>
5
+ #include <stdint.h>
6
+ #include <stdio.h>
7
+ #include <stdlib.h>
8
+ #include <string.h>
9
+
10
+ #include <ruby.h>
11
+
12
+ #include "mem.h"
13
+
14
+ typedef struct _rec {
15
+ struct _rec *next;
16
+ const void *ptr;
17
+ size_t size;
18
+ const char *file;
19
+ int line;
20
+ bool ruby;
21
+ } *Rec;
22
+
23
+ typedef struct _rep {
24
+ struct _rep *next;
25
+ size_t size;
26
+ const char *file;
27
+ int line;
28
+ int cnt;
29
+ } *Rep;
30
+
31
+ #ifdef MEM_DEBUG
32
+
33
+ static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
34
+ static Rec recs = NULL;
35
+ static const char mem_pad[] = "--- This is a memory pad and should not change until being freed. ---";
36
+
37
+ void*
38
+ oj_malloc(size_t size, const char *file, int line) {
39
+ void *ptr = malloc(size + sizeof(mem_pad));
40
+
41
+ if (NULL != ptr) {
42
+ Rec r = (Rec)malloc(sizeof(struct _rec));
43
+
44
+ if (NULL != r) {
45
+ strcpy(((char*)ptr) + size, mem_pad);
46
+ r->ptr = ptr;
47
+ r->size = size;
48
+ r->file = file;
49
+ r->line = line;
50
+ r->ruby = false;
51
+ pthread_mutex_lock(&lock);
52
+ r->next = recs;
53
+ recs = r;
54
+ pthread_mutex_unlock(&lock);
55
+ } else {
56
+ free(ptr);
57
+ ptr = NULL;
58
+ }
59
+ }
60
+ return ptr;
61
+ }
62
+
63
+ void*
64
+ oj_realloc(void *orig, size_t size, const char *file, int line) {
65
+ void *ptr = realloc(orig, size + sizeof(mem_pad));
66
+ Rec r;
67
+
68
+ if (NULL != ptr) {
69
+ strcpy(((char*)ptr) + size, mem_pad);
70
+ pthread_mutex_lock(&lock);
71
+ for (r = recs; NULL != r; r = r->next) {
72
+ if (orig == r->ptr) {
73
+ r->ptr = ptr;
74
+ r->size = size;
75
+ r->file = file;
76
+ r->line = line;
77
+ r->ruby = false;
78
+ break;
79
+ }
80
+ }
81
+ pthread_mutex_unlock(&lock);
82
+ if (NULL == r) {
83
+ printf("Realloc at %s:%d (%p) not allocated.\n", file, line, orig);
84
+ }
85
+ }
86
+ return ptr;
87
+ }
88
+
89
+ void*
90
+ oj_calloc(size_t count, size_t size, const char *file, int line) {
91
+ void *ptr;
92
+
93
+ size *= count;
94
+ if (NULL != (ptr = malloc(size + sizeof(mem_pad)))) {
95
+ Rec r = (Rec)malloc(sizeof(struct _rec));
96
+
97
+ if (NULL != r) {
98
+ memset(ptr, 0, size);
99
+ strcpy(((char*)ptr) + size, mem_pad);
100
+ r->ptr = ptr;
101
+ r->size = size;
102
+ r->file = file;
103
+ r->line = line;
104
+ r->ruby = false;
105
+ pthread_mutex_lock(&lock);
106
+ r->next = recs;
107
+ recs = r;
108
+ pthread_mutex_unlock(&lock);
109
+ } else {
110
+ free(ptr);
111
+ ptr = NULL;
112
+ }
113
+ }
114
+ return ptr;
115
+ }
116
+
117
+ void*
118
+ oj_r_alloc(size_t size, const char *file, int line) {
119
+ void *ptr = ruby_xmalloc(size + sizeof(mem_pad));
120
+
121
+ if (NULL != ptr) {
122
+ Rec r = (Rec)malloc(sizeof(struct _rec));
123
+
124
+ if (NULL != r) {
125
+ strcpy(((char*)ptr) + size, mem_pad);
126
+ r->ptr = ptr;
127
+ r->size = size;
128
+ r->file = file;
129
+ r->line = line;
130
+ r->ruby = true;
131
+ pthread_mutex_lock(&lock);
132
+ r->next = recs;
133
+ recs = r;
134
+ pthread_mutex_unlock(&lock);
135
+ } else {
136
+ free(ptr);
137
+ ptr = NULL;
138
+ }
139
+ }
140
+ return ptr;
141
+ }
142
+
143
+ void*
144
+ oj_r_realloc(void *orig, size_t size, const char *file, int line) {
145
+ void *ptr = ruby_xrealloc2(orig, 1, size + sizeof(mem_pad));
146
+ Rec r;
147
+
148
+ if (NULL != ptr) {
149
+ strcpy(((char*)ptr) + size, mem_pad);
150
+ pthread_mutex_lock(&lock);
151
+ for (r = recs; NULL != r; r = r->next) {
152
+ if (orig == r->ptr) {
153
+ r->ptr = ptr;
154
+ r->size = size;
155
+ r->file = file;
156
+ r->line = line;
157
+ r->ruby = true;
158
+ break;
159
+ }
160
+ }
161
+ pthread_mutex_unlock(&lock);
162
+ if (NULL == r) {
163
+ printf("Realloc at %s:%d (%p) not allocated.\n", file, line, orig);
164
+ }
165
+ }
166
+ return ptr;
167
+ }
168
+
169
+
170
+ void
171
+ oj_freed(void *ptr, const char *file, int line, bool ruby) {
172
+ if (NULL != ptr) {
173
+ Rec r = NULL;
174
+ Rec prev = NULL;
175
+
176
+ pthread_mutex_lock(&lock);
177
+ for (r = recs; NULL != r; r = r->next) {
178
+ if (ptr == r->ptr) {
179
+ if (NULL == prev) {
180
+ recs = r->next;
181
+ } else {
182
+ prev->next = r->next;
183
+ }
184
+ break;
185
+ }
186
+ prev = r;
187
+ }
188
+ pthread_mutex_unlock(&lock);
189
+ if (NULL == r) {
190
+ printf("Free at %s:%d (%p) not allocated or already freed.\n", file, line, ptr);
191
+ } else {
192
+ char *pad = (char*)r->ptr + r->size;
193
+
194
+ if (r->ruby != ruby) {
195
+ if (r->ruby) {
196
+ printf("Memory at %s:%d (%p) allocated with Ruby allocator and freed with stdlib free.\n", file, line, ptr);
197
+ } else {
198
+ printf("Memory at %s:%d (%p) allocated with stdlib allocator and freed with Ruby free.\n", file, line, ptr);
199
+ }
200
+ }
201
+ if (0 != strcmp(mem_pad, pad)) {
202
+ uint8_t *p;
203
+ uint8_t *end = (uint8_t*)pad + sizeof(mem_pad);
204
+
205
+ printf("Memory at %s:%d (%p) write outside allocated.\n", file, line, ptr);
206
+ for (p = (uint8_t*)pad; p < end; p++) {
207
+ if (0x20 < *p && *p < 0x7f) {
208
+ printf("%c ", *p);
209
+ } else {
210
+ printf("%02x ", *(uint8_t*)p);
211
+ }
212
+ }
213
+ printf("\n");
214
+ }
215
+ free(r);
216
+ }
217
+ }
218
+ }
219
+
220
+ void
221
+ oj_r_free(void *ptr, const char *file, int line) {
222
+ oj_freed(ptr, file, line, true);
223
+ xfree(ptr);
224
+ }
225
+
226
+
227
+ void
228
+ oj_free(void *ptr, const char *file, int line) {
229
+ oj_freed(ptr, file, line, false);
230
+ free(ptr);
231
+ }
232
+
233
+ char*
234
+ oj_mem_strdup(const char *str, const char *file, int line) {
235
+ size_t size = strlen(str) + 1;
236
+ char *ptr = (char*)malloc(size + sizeof(mem_pad));
237
+
238
+ if (NULL != ptr) {
239
+ Rec r = (Rec)malloc(sizeof(struct _rec));
240
+
241
+ if (NULL != r) {
242
+ strcpy(ptr, str);
243
+ strcpy(((char*)ptr) + size, mem_pad);
244
+ r->ptr = (void*)ptr;
245
+ r->size = size;
246
+ r->file = file;
247
+ r->line = line;
248
+ r->ruby = false;
249
+ pthread_mutex_lock(&lock);
250
+ r->next = recs;
251
+ recs = r;
252
+ pthread_mutex_unlock(&lock);
253
+ } else {
254
+ free(ptr);
255
+ ptr = NULL;
256
+ }
257
+ }
258
+ return ptr;
259
+ }
260
+
261
+ #endif
262
+
263
+ #ifdef MEM_DEBUG
264
+
265
+ static Rep
266
+ update_reps(Rep reps, Rec r) {
267
+ Rep rp = reps;
268
+
269
+ for (; NULL != rp; rp = rp->next) {
270
+ if (rp->line == r->line && (rp->file == r->file || 0 == strcmp(rp->file, r->file))) {
271
+ rp->size += r->size;
272
+ rp->cnt++;
273
+ break;
274
+ }
275
+ }
276
+ if (NULL == rp &&
277
+ NULL != (rp = (Rep)malloc(sizeof(struct _rep)))) {
278
+ rp->size = r->size;
279
+ rp->file = r->file;
280
+ rp->line = r->line;
281
+ rp->cnt = 1;
282
+ rp->next = reps;
283
+ reps = rp;
284
+ }
285
+ return reps;
286
+ }
287
+
288
+ static void
289
+ print_stats() {
290
+ printf("\n--- Memory Usage Report --------------------------------------------------------\n");
291
+ pthread_mutex_lock(&lock);
292
+
293
+ if (NULL == recs) {
294
+ printf("No memory leaks\n");
295
+ } else {
296
+ Rep reps = NULL;
297
+ Rep rp;
298
+ Rec r;
299
+ size_t leaked = 0;
300
+
301
+ for (r = recs; NULL != r; r = r->next) {
302
+ reps = update_reps(reps, r);
303
+ }
304
+ while (NULL != (rp = reps)) {
305
+ reps = rp->next;
306
+ printf("%16s:%3d %8lu bytes over %d occurances allocated and not freed.\n", rp->file, rp->line, rp->size, rp->cnt);
307
+ leaked += rp->size;
308
+ free(rp);
309
+ }
310
+ printf("%lu bytes leaked\n", leaked);
311
+ }
312
+ pthread_mutex_unlock(&lock);
313
+ printf("--------------------------------------------------------------------------------\n");
314
+ }
315
+
316
+ #endif
317
+
318
+ void
319
+ oj_mem_report() {
320
+ #ifdef MEM_DEBUG
321
+ rb_gc();
322
+ print_stats();
323
+ #endif
324
+ }
data/ext/oj/mem.h ADDED
@@ -0,0 +1,53 @@
1
+ // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
+
3
+ #ifndef OJ_MEM_H
4
+ #define OJ_MEM_H
5
+
6
+ #include <stdio.h>
7
+ #include <stdlib.h>
8
+ #include <string.h>
9
+
10
+ #ifdef MEM_DEBUG
11
+
12
+ #define OJ_MALLOC(size) oj_malloc(size, __FILE__, __LINE__)
13
+ #define OJ_REALLOC(ptr, size) oj_realloc(ptr, size, __FILE__, __LINE__)
14
+ #define OJ_CALLOC(count, size) oj_calloc(count, size, __FILE__, __LINE__)
15
+ #define OJ_FREE(ptr) oj_free(ptr, __FILE__, __LINE__)
16
+
17
+ #define OJ_R_ALLOC(type) oj_r_alloc(sizeof(type), __FILE__, __LINE__)
18
+ #define OJ_R_ALLOC_N(type, n) (type *)oj_r_alloc(sizeof(type) * (n), __FILE__, __LINE__)
19
+ #define OJ_R_REALLOC_N(ptr, type, n) ((ptr) = (type*)oj_r_realloc(ptr, (sizeof(type) * (n)), __FILE__, __LINE__))
20
+ #define OJ_R_FREE(ptr) oj_r_free(ptr, __FILE__, __LINE__)
21
+
22
+ #define OJ_STRDUP(str) oj_mem_strdup(str, __FILE__, __LINE__)
23
+
24
+ extern void* oj_malloc(size_t size, const char *file, int line);
25
+ extern void* oj_realloc(void *ptr, size_t size, const char *file, int line);
26
+ extern void* oj_calloc(size_t count, size_t size, const char *file, int line);
27
+ extern void oj_free(void *ptr, const char *file, int line);
28
+
29
+ extern void* oj_r_alloc(size_t size, const char *file, int line);
30
+ extern void* oj_r_realloc(void *ptr, size_t size, const char *file, int line);
31
+ extern void oj_r_free(void *ptr, const char *file, int line);
32
+
33
+ extern char* oj_mem_strdup(const char *str, const char *file, int line);
34
+
35
+ #else
36
+
37
+ #define OJ_MALLOC(size) malloc(size)
38
+ #define OJ_REALLOC(ptr, size) realloc(ptr, size)
39
+ #define OJ_CALLOC(count, size) calloc(count, size)
40
+ #define OJ_FREE(ptr) free(ptr)
41
+
42
+ #define OJ_R_ALLOC(type) RB_ALLOC(type)
43
+ #define OJ_R_ALLOC_N(type, n) RB_ALLOC_N(type, n)
44
+ #define OJ_R_REALLOC_N(ptr, type, n) RB_REALLOC_N(ptr, type, n)
45
+ #define OJ_R_FREE(ptr) xfree(ptr)
46
+
47
+ #define OJ_STRDUP(str) strdup(str)
48
+
49
+ #endif
50
+
51
+ extern void oj_mem_report();
52
+
53
+ #endif /* OJ_MEM_H */
data/ext/oj/mimic_json.c CHANGED
@@ -1,6 +1,7 @@
1
1
  // Copyright (c) 2012, 2017 Peter Ohler. All rights reserved.
2
2
  // Licensed under the MIT License. See LICENSE file in the project root for license details.
3
3
 
4
+ #include "mem.h"
4
5
  #include "dump.h"
5
6
  #include "encode.h"
6
7
  #include "oj.h"
@@ -664,7 +665,7 @@ static VALUE mimic_set_create_id(VALUE self, VALUE id) {
664
665
 
665
666
  if (NULL != oj_default_options.create_id) {
666
667
  if (oj_json_class != oj_default_options.create_id) {
667
- xfree((char *)oj_default_options.create_id);
668
+ OJ_R_FREE((char *)oj_default_options.create_id);
668
669
  }
669
670
  oj_default_options.create_id = NULL;
670
671
  oj_default_options.create_id_len = 0;
@@ -672,7 +673,7 @@ static VALUE mimic_set_create_id(VALUE self, VALUE id) {
672
673
  if (Qnil != id) {
673
674
  size_t len = RSTRING_LEN(id) + 1;
674
675
 
675
- oj_default_options.create_id = ALLOC_N(char, len);
676
+ oj_default_options.create_id = OJ_R_ALLOC_N(char, len);
676
677
  strcpy((char *)oj_default_options.create_id, StringValuePtr(id));
677
678
  oj_default_options.create_id_len = len - 1;
678
679
  }
data/ext/oj/object.c CHANGED
@@ -352,7 +352,7 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
352
352
  }
353
353
  return 1;
354
354
  } else if (3 <= klen && '#' == key[1]) {
355
- volatile VALUE *a;
355
+ volatile const VALUE *a;
356
356
 
357
357
  if (2 != len) {
358
358
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
@@ -546,7 +546,7 @@ WHICH_TYPE:
546
546
  } else {
547
547
  if (3 <= klen && '^' == *key && '#' == key[1] && T_ARRAY == rb_type(value)) {
548
548
  long len = RARRAY_LEN(value);
549
- volatile VALUE *a = RARRAY_CONST_PTR(value);
549
+ volatile const VALUE *a = RARRAY_CONST_PTR(value);
550
550
 
551
551
  if (2 != len) {
552
552
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
data/ext/oj/odd.c CHANGED
@@ -1,6 +1,7 @@
1
1
  // Copyright (c) 2011 Peter Ohler. All rights reserved.
2
2
  // Licensed under the MIT License. See LICENSE file in the project root for license details.
3
3
 
4
+ #include "mem.h"
4
5
  #include "odd.h"
5
6
 
6
7
  #include <string.h>
@@ -68,7 +69,7 @@ void print_all_odds(const char *label) {
68
69
  }
69
70
 
70
71
  static Odd odd_create(void) {
71
- Odd odd = ALLOC(struct _odd);
72
+ Odd odd = OJ_R_ALLOC(struct _odd);
72
73
 
73
74
  memset(odd, 0, sizeof(struct _odd));
74
75
  odd->next = odds;
@@ -172,7 +173,7 @@ Odd oj_get_oddc(const char *classname, size_t len) {
172
173
  }
173
174
 
174
175
  OddArgs oj_odd_alloc_args(Odd odd) {
175
- OddArgs oa = ALLOC_N(struct _oddArgs, 1);
176
+ OddArgs oa = OJ_R_ALLOC_N(struct _oddArgs, 1);
176
177
  VALUE *a;
177
178
  int i;
178
179
 
@@ -184,7 +185,7 @@ OddArgs oj_odd_alloc_args(Odd odd) {
184
185
  }
185
186
 
186
187
  void oj_odd_free(OddArgs args) {
187
- xfree(args);
188
+ OJ_R_FREE(args);
188
189
  }
189
190
 
190
191
  int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value) {
@@ -210,7 +211,7 @@ void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt,
210
211
  odd = odd_create();
211
212
  odd->clas = clas;
212
213
  rb_gc_register_mark_object(odd->clas);
213
- if (NULL == (odd->classname = strdup(rb_class2name(clas)))) {
214
+ if (NULL == (odd->classname = OJ_STRDUP(rb_class2name(clas)))) {
214
215
  rb_raise(rb_eNoMemError, "for class name.");
215
216
  }
216
217
  odd->clen = strlen(odd->classname);
@@ -224,13 +225,13 @@ void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt,
224
225
  *fp = 0;
225
226
  switch (rb_type(*members)) {
226
227
  case T_STRING:
227
- if (NULL == (*np = strdup(RSTRING_PTR(*members)))) {
228
+ if (NULL == (*np = OJ_STRDUP(RSTRING_PTR(*members)))) {
228
229
  rb_raise(rb_eNoMemError, "for attribute name.");
229
230
  }
230
231
  break;
231
232
  case T_SYMBOL:
232
233
  // The symbol can move and invalidate the name so make a copy.
233
- if (NULL == (*np = strdup(rb_id2name(SYM2ID(*members))))) {
234
+ if (NULL == (*np = OJ_STRDUP(rb_id2name(SYM2ID(*members))))) {
234
235
  rb_raise(rb_eNoMemError, "for attribute name.");
235
236
  }
236
237
  break;
data/ext/oj/oj.c CHANGED
@@ -11,6 +11,7 @@
11
11
  #include <sys/types.h>
12
12
  #include <unistd.h>
13
13
 
14
+ #include "mem.h"
14
15
  #include "dump.h"
15
16
  #include "encode.h"
16
17
  #include "intern.h"
@@ -782,7 +783,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
782
783
  } else if (create_id_sym == k) {
783
784
  if (Qnil == v) {
784
785
  if (oj_json_class != oj_default_options.create_id && NULL != copts->create_id) {
785
- xfree((char *)oj_default_options.create_id);
786
+ OJ_R_FREE((char *)oj_default_options.create_id);
786
787
  }
787
788
  copts->create_id = NULL;
788
789
  copts->create_id_len = 0;
@@ -791,7 +792,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
791
792
 
792
793
  len = RSTRING_LEN(v);
793
794
  if (len != copts->create_id_len || 0 != strcmp(copts->create_id, str)) {
794
- copts->create_id = ALLOC_N(char, len + 1);
795
+ copts->create_id = OJ_R_ALLOC_N(char, len + 1);
795
796
  strcpy((char *)copts->create_id, str);
796
797
  copts->create_id_len = len;
797
798
  }
@@ -911,7 +912,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
911
912
  copts->array_class = v;
912
913
  }
913
914
  } else if (ignore_sym == k) {
914
- xfree(copts->ignore);
915
+ OJ_R_FREE(copts->ignore);
915
916
  copts->ignore = NULL;
916
917
  if (Qnil != v) {
917
918
  int cnt;
@@ -921,7 +922,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
921
922
  if (0 < cnt) {
922
923
  int i;
923
924
 
924
- copts->ignore = ALLOC_N(VALUE, cnt + 1);
925
+ copts->ignore = OJ_R_ALLOC_N(VALUE, cnt + 1);
925
926
  for (i = 0; i < cnt; i++) {
926
927
  copts->ignore[i] = RARRAY_AREF(v, i);
927
928
  }
@@ -1159,7 +1160,7 @@ static VALUE load_file(int argc, VALUE *argv, VALUE self) {
1159
1160
  WCHAR *wide_path;
1160
1161
  wide_path = rb_w32_mbstr_to_wstr(CP_UTF8, path, -1, NULL);
1161
1162
  fd = rb_w32_wopen(wide_path, O_RDONLY);
1162
- free(wide_path);
1163
+ OJ_FREE(wide_path);
1163
1164
  }
1164
1165
  #else
1165
1166
  fd = open(path, O_RDONLY);
@@ -1724,6 +1725,10 @@ debug_odd(VALUE self, VALUE label) {
1724
1725
  return Qnil;
1725
1726
  }
1726
1727
 
1728
+ static VALUE mem_report(VALUE self) {
1729
+ oj_mem_report();
1730
+ return Qnil;
1731
+ }
1727
1732
 
1728
1733
  /* Document-module: Oj
1729
1734
  *
@@ -1812,6 +1817,8 @@ void Init_oj(void) {
1812
1817
 
1813
1818
  rb_define_module_function(Oj, "optimize_rails", oj_optimize_rails, 0);
1814
1819
 
1820
+ rb_define_module_function(Oj, "mem_report", mem_report, 0);
1821
+
1815
1822
  oj_add_value_id = rb_intern("add_value");
1816
1823
  oj_array_append_id = rb_intern("array_append");
1817
1824
  oj_array_end_id = rb_intern("array_end");
data/ext/oj/parse.c CHANGED
@@ -10,6 +10,7 @@
10
10
  #include <string.h>
11
11
  #include <unistd.h>
12
12
 
13
+ #include "mem.h"
13
14
  #include "buf.h"
14
15
  #include "encode.h"
15
16
  #include "oj.h"
@@ -87,7 +88,7 @@ static void add_value(ParseInfo pi, VALUE rval) {
87
88
  pi->hash_set_value(pi, parent, rval);
88
89
  if (0 != parent->key && 0 < parent->klen &&
89
90
  (parent->key < pi->json || pi->cur < parent->key)) {
90
- xfree((char *)parent->key);
91
+ OJ_R_FREE((char *)parent->key);
91
92
  parent->key = 0;
92
93
  }
93
94
  parent->next = NEXT_HASH_COMMA;
@@ -236,7 +237,8 @@ static void read_escaped_str(ParseInfo pi, const char *start) {
236
237
 
237
238
  for (s = pi->cur; '"' != *s;) {
238
239
  const char *scanned = scan_func(s, pi->end);
239
- if (scanned >= pi->end || '\0' == *s) {
240
+ if (scanned >= pi->end || '\0' == *scanned) {
241
+ //if (scanned >= pi->end) {
240
242
  oj_set_error_at(pi,
241
243
  oj_parse_error_class,
242
244
  __FILE__,
@@ -333,7 +335,7 @@ static void read_escaped_str(ParseInfo pi, const char *start) {
333
335
  case NEXT_HASH_KEY:
334
336
  if (Qundef == (parent->key_val = pi->hash_key(pi, buf.head, buf_len(&buf)))) {
335
337
  parent->klen = buf_len(&buf);
336
- parent->key = malloc(parent->klen + 1);
338
+ parent->key = OJ_MALLOC(parent->klen + 1);
337
339
  memcpy((char *)parent->key, buf.head, parent->klen);
338
340
  *(char *)(parent->key + parent->klen) = '\0';
339
341
  } else {
@@ -347,7 +349,7 @@ static void read_escaped_str(ParseInfo pi, const char *start) {
347
349
  pi->hash_set_cstr(pi, parent, buf.head, buf_len(&buf), start);
348
350
  if (0 != parent->key && 0 < parent->klen &&
349
351
  (parent->key < pi->json || pi->cur < parent->key)) {
350
- xfree((char *)parent->key);
352
+ OJ_R_FREE((char *)parent->key);
351
353
  parent->key = 0;
352
354
  }
353
355
  parent->next = NEXT_HASH_COMMA;
@@ -417,7 +419,7 @@ static void read_str(ParseInfo pi) {
417
419
  pi->hash_set_cstr(pi, parent, str, pi->cur - str, str);
418
420
  if (0 != parent->key && 0 < parent->klen &&
419
421
  (parent->key < pi->json || pi->cur < parent->key)) {
420
- xfree((char *)parent->key);
422
+ OJ_R_FREE((char *)parent->key);
421
423
  parent->key = 0;
422
424
  }
423
425
  parent->next = NEXT_HASH_COMMA;
@@ -616,7 +618,7 @@ static void read_num(ParseInfo pi) {
616
618
  pi->hash_set_num(pi, parent, &ni);
617
619
  if (0 != parent->key && 0 < parent->klen &&
618
620
  (parent->key < pi->json || pi->cur < parent->key)) {
619
- xfree((char *)parent->key);
621
+ OJ_R_FREE((char *)parent->key);
620
622
  parent->key = 0;
621
623
  }
622
624
  parent->next = NEXT_HASH_COMMA;
@@ -870,12 +872,12 @@ oj_num_as_value(NumInfo ni) {
870
872
  buf[ni->len] = '\0';
871
873
  rnum = rb_cstr_to_inum(buf, 10, 0);
872
874
  } else {
873
- char *buf = ALLOC_N(char, ni->len + 1);
875
+ char *buf = OJ_R_ALLOC_N(char, ni->len + 1);
874
876
 
875
877
  memcpy(buf, ni->str, ni->len);
876
878
  buf[ni->len] = '\0';
877
879
  rnum = rb_cstr_to_inum(buf, 10, 0);
878
- xfree(buf);
880
+ OJ_R_FREE(buf);
879
881
  }
880
882
  } else {
881
883
  if (ni->neg) {
@@ -1076,12 +1078,12 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
1076
1078
  size_t len = lseek(fd, 0, SEEK_END);
1077
1079
 
1078
1080
  lseek(fd, 0, SEEK_SET);
1079
- buf = ALLOC_N(char, len + 1);
1081
+ buf = OJ_R_ALLOC_N(char, len + 1);
1080
1082
  pi->json = buf;
1081
1083
  pi->end = buf + len;
1082
1084
  if (0 >= (cnt = read(fd, (char *)pi->json, len)) || cnt != (ssize_t)len) {
1083
1085
  if (0 != buf) {
1084
- xfree(buf);
1086
+ OJ_R_FREE(buf);
1085
1087
  }
1086
1088
  rb_raise(rb_eIOError, "failed to read from IO Object.");
1087
1089
  }
@@ -1163,9 +1165,9 @@ CLEANUP:
1163
1165
  oj_circ_array_free(pi->circ_array);
1164
1166
  }
1165
1167
  if (0 != buf) {
1166
- xfree(buf);
1168
+ OJ_R_FREE(buf);
1167
1169
  } else if (free_json) {
1168
- xfree(json);
1170
+ OJ_R_FREE(json);
1169
1171
  }
1170
1172
  stack_cleanup(&pi->stack);
1171
1173
  if (pi->str_rx.head != oj_default_options.str_rx.head) {