It was my assumption that during shutdown the objects would be freed leaf objects first, and a mark and sweep like approach. It seems however that Ruby just walks an object table and frees each in entry order. For native (C/C++) object graphs this can lead to out of order deallocations. In my particular case this leads to a SEGV. I was hoping to avoid pulling in Boost to add reference counting, was hoping that the GC integration with Mark and Sweep would help, but it would appear it does not? Would someone please comment on approaches to systematically free C++ objects (in a Ruby C Extension) in the proper order? Am I left solely with a reference counting approach? Thanks, Bob
on 2012-11-21 03:00
on 2012-11-21 15:32
Robert Buck wrote in post #1085583: > It was my assumption that during shutdown the objects would be freed > leaf objects first, and a mark and sweep like approach. It seems however > that Ruby just walks an object table and frees each in entry order. > > For native (C/C++) object graphs this can lead to out of order > deallocations. In my particular case this leads to a SEGV. Hi, If you have to free the objects in certain order, in C/C++ you have to record only one Ruby object which is the root, then you create pointers to all other leaf (non-root) Ruby objects; in the free function pointers, you set all the leaf (non-root) Ruby objects as NULL. Hopefully you don't create too many temporary leaf (non-root) objects, as all we be freed only when root is freed. Regards, Bill
on 2012-11-21 16:09
Unsure if this really applies. Could you restate? I am not quite following you. Let me provide additional details... The use case is a database driver where a connection begets prepared statement objects which begets result set objects which begets column info objects. At each layer of objects we wrap its corresponding struct using Data_Wrap_Struct as each object has functions (written in C) exposed to Ruby that may operate on it. I did set this up so that the child objects have a VALUE reference to its parent. But it certainly is the case that Ruby does not do one last Mark and Sweep before it shuts down after removing all entries from the object table. Instead it appears as though Ruby simply does a bulk delete willy-nilly with no concerns about deletion order (which minimally should occur in at least reverse order of allocation, again which Ruby does not do). Admin Tensor wrote in post #1085669: > Robert Buck wrote in post #1085583: >> It was my assumption that during shutdown the objects would be freed >> leaf objects first, and a mark and sweep like approach. It seems however >> that Ruby just walks an object table and frees each in entry order. >> >> For native (C/C++) object graphs this can lead to out of order >> deallocations. In my particular case this leads to a SEGV. > > Hi, > > If you have to free the objects in certain order, in C/C++ you have to > record only one Ruby object which is the root, then you create pointers > to all other leaf (non-root) Ruby objects; in the free function > pointers, you set all the leaf (non-root) Ruby objects as NULL. > Hopefully you don't create too many temporary leaf (non-root) objects, > as all we be freed only when root is freed. > > Regards, > > Bill
on 2012-11-21 16:13
For what its worth, I just tried hooking into the at exit hook at the C/C++ side. But that gets called AFTER Ruby bulk dumps/deletes all objects out of order. I was hoping to have this intercepted prior to global object deletion so that I could put the driver into a special mode, the don't free anything mode (since memory will be cleaned up anyways when the proc terminates).
on 2012-11-21 16:44
Robert Buck wrote in post #1085679: > For what its worth, I just tried hooking into the at exit hook at the > C/C++ side. But that gets called AFTER Ruby bulk dumps/deletes all > objects out of order. I was hoping to have this intercepted prior to > global object deletion so that I could put the driver into a special > mode, the don't free anything mode (since memory will be cleaned up > anyways when the proc terminates). Hi, I am sorry that I don't know the precise situation. If you just want memory to be cleaned up automatically when the proc terminates, then in Data_Wrap_Struct(klass, mark, free, ptr), just set NULL for the "free" pointer. But of course this assumes that the SEGV occurs because of the C-related code, not Ruby-related code, and hopefully the database also does not require special handling during automatic termination. Regards, Bill
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.