簡體   English   中英

嵌入式Ruby GC和包裝的結構

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM