[英]Embedded Ruby GC and wrapped structs
我有一個嵌入了ruby 1.9.3的win32控制台應用程序,並且我遇到了ruby GC和帶有包裝的C結構(包括指向大數據的指針)的對象的問題。
經過一些測試,當孤立對象占用一些內存時,ruby似乎在運行GC。 問題在於ruby沒有考慮struct指針占用的內存大小,因此它不會啟動GC,因為它認為那些孤立對象太小並且不會占用太多內存。
我制作了一個示例應用程序,該應用程序將崩潰,因為它會在其包裝的結構中創建許多帶有大數據的對象,這是代碼:
#include <ruby.h>
typedef struct TestClassStructS {
byte* bytes;
} TestClassStruct;
static void testClassFree(TestClassStruct *p) {
delete p->bytes;
delete p;
}
VALUE testClassNew(VALUE klass) {
TestClassStruct* ptr = new TestClassStruct();
ptr->bytes = new byte[1024 * 1024 * 5]();
VALUE obj = Data_Wrap_Struct(klass, NULL, testClassFree, ptr);
rb_obj_call_init(obj, 0, 0);
return obj;
}
VALUE testClassInitialize(VALUE self) {
return self;
}
typedef VALUE (*rubyfunc)(...);
VALUE require_wrap(VALUE arg)
{
return rb_eval_string("GC.enable; loop do; TestClass.new; end");
}
int main(int argc, char** argv[])
{
RUBY_INIT_STACK;
ruby_init();
//freopen("CON", "w", stdout);
ruby_init_loadpath();
ruby_sysinit(&argc, argv);
VALUE testClass = rb_define_class("TestClass", rb_cObject);
rb_define_singleton_method(testClass, "new", (rubyfunc)testClassNew, 0);
rb_define_method(testClass, "initialize", (rubyfunc)testClassInitialize, 0);
int error;
VALUE result = rb_protect(require_wrap, 0, &error);
if (error)
{
VALUE lasterr = rb_gv_get("$!");
VALUE message = rb_obj_as_string(lasterr);
printf(StringValuePtr(message));
}
return ruby_cleanup(0);
}
這不是真實情況,但是讓我擔心,在某些情況下,如果GC不啟動,我的應用程序可能會占用過多內存。
我可以通過定期調用GC.start來解決此問題,但對我來說這似乎是一個骯臟的解決方案。
如果有一種方法可以讓ruby在某些對象被孤立時優先排序垃圾回收,或者告訴ruby c結構在內存中的實際大小,那將是一個不錯的解決方案,但是我不知道ruby api是否包含這樣的東西,我找不到那樣的東西。
如果可以,請使用xmalloc(我認為來自ruby.h)來分配內存。 也就是說,到目前為止,確保下一次GC觸發占用分配內存的唯一方法。
有一個新的dsize函數注冊了包裝的C結構,但似乎在ruby 1.9.3中還沒有使用(還?)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.