Skip to content

Commit 2088e02

Browse files
author
Ashe Connor
authored
Merge pull request #17 from github/kivikakk/leaks
Fix memory leaks
2 parents aefcef8 + 4b7b7b7 commit 2088e02

1 file changed

Lines changed: 79 additions & 24 deletions

File tree

ext/version_sorter/version_sorter.c

Lines changed: 79 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -171,43 +171,75 @@ parse_version_number(const char *string)
171171
return version;
172172
}
173173

174+
struct sort_context {
175+
VALUE rb_self;
176+
VALUE rb_version_array;
177+
compare_callback_t *cmp;
178+
struct version_number **versions;
179+
};
180+
174181
static VALUE
175-
rb_version_sort_1(VALUE rb_self, VALUE rb_version_array, compare_callback_t cmp)
182+
rb_version_sort_1_cb(VALUE arg)
176183
{
177-
struct version_number **versions;
184+
struct sort_context *context = (struct sort_context *)arg;
178185
long length, i;
179186
VALUE *rb_version_ptr;
180187

181-
Check_Type(rb_version_array, T_ARRAY);
182-
183-
length = RARRAY_LEN(rb_version_array);
184-
if (!length)
185-
return rb_ary_new();
186-
187-
versions = xcalloc(length, sizeof(struct version_number *));
188-
188+
length = RARRAY_LEN(context->rb_version_array);
189189
for (i = 0; i < length; ++i) {
190190
VALUE rb_version, rb_version_string;
191191

192-
rb_version = rb_ary_entry(rb_version_array, i);
192+
rb_version = rb_ary_entry(context->rb_version_array, i);
193193
if (rb_block_given_p())
194194
rb_version_string = rb_yield(rb_version);
195195
else
196196
rb_version_string = rb_version;
197197

198-
versions[i] = parse_version_number(StringValueCStr(rb_version_string));
199-
versions[i]->rb_version = rb_version;
198+
context->versions[i] = parse_version_number(StringValueCStr(rb_version_string));
199+
context->versions[i]->rb_version = rb_version;
200+
}
201+
202+
qsort(context->versions, length, sizeof(struct version_number *), context->cmp);
203+
rb_version_ptr = RARRAY_PTR(context->rb_version_array);
204+
205+
for (i = 0; i < length; ++i) {
206+
rb_version_ptr[i] = context->versions[i]->rb_version;
200207
}
201208

202-
qsort(versions, length, sizeof(struct version_number *), cmp);
203-
rb_version_ptr = RARRAY_PTR(rb_version_array);
209+
return context->rb_version_array;
210+
}
211+
212+
static VALUE
213+
rb_version_sort_1(VALUE rb_self, VALUE rb_version_array, compare_callback_t cmp)
214+
{
215+
long length, i;
216+
int exception;
217+
218+
Check_Type(rb_version_array, T_ARRAY);
219+
220+
length = RARRAY_LEN(rb_version_array);
221+
if (!length)
222+
return rb_ary_new();
223+
224+
struct sort_context context = {
225+
rb_self,
226+
rb_version_array,
227+
cmp,
228+
xcalloc(length, sizeof(struct version_number *)),
229+
};
230+
231+
VALUE result = rb_protect(rb_version_sort_1_cb, (VALUE)&context, &exception);
204232

205233
for (i = 0; i < length; ++i) {
206-
rb_version_ptr[i] = versions[i]->rb_version;
207-
xfree(versions[i]);
234+
xfree(context.versions[i]);
208235
}
209-
xfree(versions);
210-
return rb_version_array;
236+
xfree(context.versions);
237+
238+
if (exception) {
239+
rb_jump_tag(exception);
240+
}
241+
242+
return result;
211243
}
212244

213245
static VALUE
@@ -234,16 +266,39 @@ rb_version_sort_r_bang(VALUE rb_self, VALUE rb_versions)
234266
return rb_version_sort_1(rb_self, rb_versions, version_compare_cb_r);
235267
}
236268

269+
struct compare_context {
270+
VALUE rb_version_a, rb_version_b;
271+
struct version_number *version_a, *version_b;
272+
};
273+
274+
static VALUE
275+
rb_version_compare_cb(VALUE arg)
276+
{
277+
struct compare_context *context = (struct compare_context *)arg;
278+
279+
context->version_a = parse_version_number(StringValueCStr(context->rb_version_a));
280+
context->version_b = parse_version_number(StringValueCStr(context->rb_version_b));
281+
282+
return INT2NUM(version_compare_cb(&context->version_a, &context->version_b));
283+
}
284+
237285
static VALUE
238286
rb_version_compare(VALUE rb_self, VALUE rb_version_a, VALUE rb_version_b)
239287
{
240-
struct version_number *version_a = parse_version_number(StringValueCStr(rb_version_a));
241-
struct version_number *version_b = parse_version_number(StringValueCStr(rb_version_b));
288+
int exception;
289+
struct compare_context context = {
290+
rb_version_a, rb_version_b,
291+
NULL, NULL,
292+
};
242293

243-
VALUE result = INT2NUM(version_compare_cb(&version_a, &version_b));
294+
VALUE result = rb_protect(rb_version_compare_cb, (VALUE)&context, &exception);
244295

245-
xfree(version_a);
246-
xfree(version_b);
296+
xfree(context.version_a);
297+
xfree(context.version_b);
298+
299+
if (exception) {
300+
rb_jump_tag(exception);
301+
}
247302

248303
return result;
249304
}

0 commit comments

Comments
 (0)