我有一個win32控制檯應用程序與紅寶石1.9.3嵌入式,我有問題的紅寶石GC和對象與包裝C結構包括一個指向大數據的指針。嵌入式紅寶石GC和包裝結構
經過一些測試後,ruby似乎在孤立對象佔用內存時運行GC。問題是ruby沒有考慮到結構指針佔用的內存大小,所以它不會啓動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。但也許我可以設法使其工作,可能通過改變一點點gc.c 你能指點我一些關於新的dsize函數的信息嗎? – vgvgf
我有相同的一般問題(從C++分配的大結構,需要告訴Ruby的GC)。如果您對修補過的Ruby沒有問題,我會建議您簡單地添加一個公共方法,如rb_gc_announce_malloc(size)或類似的東西,它允許告訴GC有一些內存已分配。我不確定dsize方法。 –