rb_raise and memory

  • Thread starter Nikolai Weibull
  • Start date
N

Nikolai Weibull

In re.c(make_regexp):

rp = ALLOC(Regexp);
MEMZERO((char *)rp, Regexp, 1);
rp->buffer = ALLOC_N(char, 16);
rp->allocated = 16;
rp->fastmap = ALLOC_N(char, 256);
if (flags) {
rp->options = flags;
}
err = re_compile_pattern(s, len, rp);

if (err != NULL) {
rb_reg_raise(s, len, err, 0);
}
return rp;

As rb_raise is implemented with longjmp, won't this leed to
memory-leaks? I have code that works similar to this, so I'd really
like to know, so that I can clean up before I call rb_raise if
necessary,
nikolai
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: rb_raise and memory"

|As rb_raise is implemented with longjmp, won't this leed to
|memory-leaks? I have code that works similar to this, so I'd really
|like to know, so that I can clean up before I call rb_raise if
|necessary,

It's leaking. Thank you for finding it.

matz.
 
N

Nikolai Weibull

* Yukihiro Matsumoto (Mar 10, 2005 00:20):
It's leaking. Thank you for finding it.

No problem. Is there a simple workaround (other than explicitly
calling free before rb_raise), such as registering the address with the
GC? One would have to wrap it in a VALUE it seems, which isn't
great...

Anyway, I'm just curious if there's a nice way of solving this without
explicit frees,
nikolai
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: rb_raise and memory"

|> It's leaking. Thank you for finding it.
|
|No problem. Is there a simple workaround (other than explicitly
|calling free before rb_raise), such as registering the address with the
|GC? One would have to wrap it in a VALUE it seems, which isn't
|great...

There's no way for Ruby GC to handle non-VALUE data. The only
solution I can think of is moving to Boehm GC, which might be an
overkill.

matz.
 
C

Charles Mills

Nikolai said:
* Yukihiro Matsumoto (Mar 10, 2005 00:20):


No problem. Is there a simple workaround (other than explicitly
calling free before rb_raise), such as registering the address with the
GC? One would have to wrap it in a VALUE it seems, which isn't
great...

Anyway, I'm just curious if there's a nice way of solving this without
explicit frees,

One technique that typically prevents this is using an alloc function.
For example:

struct my_array {
long len;
VALUE *ptr;
};

#define GetMyArray(obj, var) /* get the struct my_array from obj */

VALUE
my_array_alloc(VALUE klass)
{
struct my_array *a = ALLOC(struct my_array);
a->len = 0;
a->ptr = 0;
/* if data wrap struct has a memory error (which is very unlikely)
* you get a memory leak. */
return Data_Wrap_Struct(...)
}

VALUE
my_array_init(VALUE array, VALUE length)
{
long len;
struct my_array *a;
GetMyArray(array, a);
assert(a->ptr == 0 && a->len == 0);
len = NUM2LONG(length);
a->ptr = ALLOC_N(VALUE, len);
a->len = len;
return array;
}

So above the ruby object is allocated and registered with the GC before
you start allocating memory for the fields (ptr in this case) of struct
my_array.
This helps prevent errors which occur during initialization from
creating memory leaks.

-Charlie
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,169
Messages
2,570,919
Members
47,459
Latest member
Vida00R129

Latest Threads

Top