2012-03-12 20 views
2

我有一個矩陣類型,其中包含一個void*數組,表示一個對象數組(這些對象都是給定矩陣中的一種類型,例如所有C整數,所有浮點數,雙精度值,各種結構或甚至可能是全部) Ruby VALUE s)。如何在Ruby擴展的VALUE *數組上完成標記?

內存分配和垃圾收集似乎正常工作,直到我嘗試創建一個VALUE s矩陣。

我已經定義了以下標記功能:

void mark_dense_storage(void* s) { 
    size_t i; 
    DENSE_STORAGE* storage = (DENSE_STORAGE*)s; 
    if (storage && storage->dtype == RUBY_OBJECT) 
    for (i = 0; i < count_dense_storage_elements(s); ++i) 
     rb_gc_mark(*((VALUE*)(storage->elements + i*sizeof(VALUE))); 
} 

所以這不僅標誌着,如果它實際上是一個VALUE矩陣 - 否則,NULL被傳遞給Data_Wrap_Struct的標記功能。

但是,當我測試一些VALUE矩陣函數(see gist)時,我得到一個段錯誤。

具體而言,它似乎出現段錯誤,我第一次嘗試VALUE*數組中調用一個Ruby方法的第一個對象:

C[i+j*ldc] = rb_funcall(C[i+j*ldc], nm_id_mult, 1, beta); // C[i+j*ldc] = C[i+j*ldc]*beta 

nm_id_mult是我Init功能定義爲rb_intern("*")一個全球性的。

這可能不是垃圾收集問題,但GC是我最少理解的Ruby的一部分 - 我的段錯誤也與this trace相同,這是海報屬於GC的部分。

所以,我的問題:

  1. 如果它是GC,什麼標記的VALUE秒的陣列的適當方法?

  2. 如果不是GC,我該如何去診斷這種類型的錯誤?我從來沒有見過這樣的事情。

編輯:

事實證明這是失敗來初始化C.

創建

換句話說VALUE S,確保做*(VALUE*)a = INT2FIX(0)您嘗試訪問之前的例子a

我仍然認爲這個問題是相關的。我還沒有設法找到在StackOverflow或其他地方用於清理和掃描垃圾回收的標記的真正好例子。如果你能提供這樣一個例子和/或解釋,我會將其標記爲這個問題的正確答案。

+1

哪個Ruby版本? – 2012-03-12 21:38:23

+0

這是Ruby 1.9.3p0(2011-10-30修訂版33570)。 – 2012-03-12 21:59:25

+0

因此,首先我要升級到Ruby 1.9.3-p125並檢查問題是否仍然存在。在p0中GC存在一些問題。 – 2012-03-12 22:15:43

回答

1

Ruby的mark-and-sweep GC分兩個階段工作。

第一階段標記活物。它通過調用每個已知「活動對象」的標記函數遞歸地工作。通過掃描每個已知Ruby線程的C堆棧或每個註冊的全局對象(有一個C函數來註冊/註銷「已知實時」對象)來生成最初的一組活動對象。對象X的標記函數應該爲X引用的每個對象調用rb_gc_mark。換句話說,你所做的就是你應該做的。然而,正如你後來注意到的那樣,沒有任何可能的VALUE是一個有效的Ruby對象。不過,我相信用Qnil初始化(即nil)會更加寶貴。