我在 rb_data_object_alloc 的 cmark 那里,对持有的对象进行了 mark,断点也能断到,确实是 mark 了,然后 mark 的这个对象的 cfree 马上就被调用了……
void CSprite::Mark(){
if (disposed) return ;
if (vectorShader) RB->GcMark(vectorShader->GetValue());
if (vectorSetting)
RB->GcMark(vectorSetting->GetValue()); // 断点1
/*
virtual void GcMark(VALUE obj) { rb_gc_mark(obj); }
*/
if (m_texture) RB->GcMark(m_texture->GetValue());
if (pixelShader) RB->GcMark(pixelShader->GetValue());
if (pixelSetting) RB->GcMark(pixelSetting->GetValue());
};
class SolidVectorShaderSetting : public VectorShaderSetting{
public:
void Setup(IDirectX * idx_);
virtual void DxSetup();
void update();
void Resize(int target); // target > 0
virtual int GetSize();
SolidVectorShaderSingleSetting * GetVector(int x);
virtual bool NeedDraw();
virtual void Mark();
static bool HaveMarkProc() { return true; }
protected:
ID3D11Buffer* vertexBuffer_;
int size;
SolidVectorShaderSingleSetting * settings;
IDirectX * idx;
bool CanDraw;
public:
SolidVectorShaderSetting(){vertexBuffer_ = NULL;CanDraw = false;size = 0;settings = NULL;}
virtual~SolidVectorShaderSetting(){
SAFE_DELETE_ARRAY(settings); // 断点2
SAFE_RELEASE(vertexBuffer_);
CanDraw = false;size = 0;
};
};
我设置了这两个断点……然后断点 1 和断点 2 分别被断到……这怎么解决。
看不出来... 建议检查一下:
*vectorSetting
放栈上了?局部作用域终结会调用析构函数的#5 楼 @luikore 绝对确定。
RgeDx11.dll!Dx11::SolidVectorShaderSetting::~SolidVectorShaderSetting() 行 63 C++
RgeDx11.dll!Dx11::SolidVectorShaderSetting::`scalar deleting destructor'(unsigned int) C++
RgeDx11.dll!Rge::CppExporter::_rb_freeDx11::SolidVectorShaderSetting(Dx11::SolidVectorShaderSetting * obj_ptr) 行 71 C++
msvcrt-ruby191.dll!62d4f399() 未知
[下面的框架可能不正确和/或缺失,没有为 msvcrt-ruby191.dll 加载符号]
msvcrt-ruby191.dll!62d524ae() 未知
msvcrt-ruby191.dll!62e538bd() 未知
……
#9 楼 @luikore 知道…… 之所以肯定 GC 有问题的另一个原因就是’‘GC.disable’‘之后世界安静了……
RgeDx11.dll!Dx11::SolidVectorShaderSetting::~SolidVectorShaderSetting() 行 62 C++ RgeDx11.dll!Dx11::SolidVectorShaderSetting::`scalar deleting destructor'(unsigned int) C++ RgeDx11.dll!Rge::CppExporter::rb_freeDx11::SolidVectorShaderSetting(Dx11::SolidVectorShaderSetting * obj_ptr) 行 71 C++ msvcr100-ruby191.dll!finalize_list(rb_objspace * objspace, RVALUE * p) 行 1808 C msvcr100-ruby191.dll!rb_gc_finalize_deferred() 行 2635 C msvcr100-ruby191.dll!rb_threadptr_execute_interrupts_rec(rb_thread_struct * th, int sched_depth) 行 1308 C msvcr100-ruby191.dll!rb_threadptr_execute_interrupts(rb_thread_struct * th) 行 1333 C msvcr100-ruby191.dll!vm_exec_core(rb_thread_struct * th, unsigned long initial) 行 1080 C msvcr100-ruby191.dll!vm_exec(rb_thread_struct * th) 行 1147 C msvcr100-ruby191.dll!invoke_block_from_c(rb_thread_struct * th, const rb_block_struct * block, unsigned long self, int argc, const unsigned long * argv, const rb_block_struct * blockptr, const RNode * cref) 行 558 C msvcr100-ruby191.dll!rb_yield_0(int argc, const unsigned long * argv) 行 740 C msvcr100-ruby191.dll!rb_yield(unsigned long val) 行 750 C msvcr100-ruby191.dll!range_each(unsigned long range) 行 494 C msvcr100-ruby191.dll!call_cfunc(unsigned long (...) * func, unsigned long recv, int len, int argc, const unsigned long * argv) 行 318 C msvcr100-ruby191.dll!vm_call_cfunc(rb_thread_struct * th, rb_control_frame_t * reg_cfp, int num, unsigned long recv, const rb_block_struct * blockptr, const rb_method_entry_struct * me) 行 404 C msvcr100-ruby191.dll!vm_call_method(rb_thread_struct * th, rb_control_frame_t * cfp, int num, const rb_block_struct * blockptr, unsigned long flag, unsigned long id, const rb_method_entry_struct * me, unsigned long recv) 行 524 C msvcr100-ruby191.dll!vm_exec_core(rb_thread_struct * th, unsigned long initial) 行 1006 C msvcr100-ruby191.dll!vm_exec(rb_thread_struct * th) 行 1147 C msvcr100-ruby191.dll!eval_string_with_cref(unsigned long self, unsigned long src, unsigned long scope, RNode * cref, const char * volatile file, volatile int line) 行 1029 C msvcr100-ruby191.dll!rb_f_eval(int argc, unsigned long * argv, unsigned long self) 行 1119 C msvcr100-ruby191.dll!call_cfunc(unsigned long (...) * func, unsigned long recv, int len, int argc, const unsigned long * argv) 行 315 C msvcr100-ruby191.dll!vm_call0(rb_thread_struct * th, unsigned long recv, unsigned long id, int argc, const unsigned long * argv, const rb_method_entry_struct * me) 行 79 C msvcr100-ruby191.dll!rb_call0(unsigned long recv, unsigned long mid, int argc, const unsigned long * argv, call_type scope, unsigned long self) 行 235 C msvcr100-ruby191.dll!rb_funcall2(unsigned long recv, unsigned long mid, int argc, const unsigned long * argv) 行 651 C RgeCore_d.dll!Rge::CRubyAbstractLayer::Funcall(unsigned long obj, unsigned long mid, int argc, ...) 行 575 C++ RgeCore_d.dll!Rge::CCoreRuntime::Require(const char * pScripts, unsigned long uScriptSize, const wchar_t * pFile, const unsigned long uLine) 行 97 C++ RgeCore_d.dll!Rge::CCoreRuntime::CoreRun2() 行 135 C++ RgeCore_d.dll!Rge::CCoreRuntime::CoreRunInProtected(unsigned long argv) 行 105 C++ msvcr100-ruby191.dll!rb_protect(unsigned long (unsigned long) * proc, unsigned long data, int * state) 行 718 C RgeCore_d.dll!Rge::CRubyAbstractLayer::ProtectRun(unsigned long (unsigned long) * proc, unsigned long args, int * state) 行 189 C++ RgeCore_d.dll!Rge::CCoreRuntime::CoreRun(const wchar_t * pScriptsName) 行 198 C++ RgePlayer_d.exe!WinMain(HINSTANCE_ * hInstance, HINSTANCE__ * hPrevInstance, char * lpCmdLine, int nShowCmd) 行 170 C++ RgePlayer_d.exe!__tmainCRTStartup() 行 528 C RgePlayer_d.exe!WinMainCRTStartup() 行 377 C
换了个有符号的 Ruby……简直悲伤。
=_= 还没碰到过 gc_mark 了却调到析构的... 我猜这个析构很可能和 gc_mark 没联系...
说不定 CSprite 对应的 ruby 对象生命比 GUI 元素提前结束,无法到达而被艹了...
#11 楼 @luikore gc_mark 的析构是包装的时候手动调用的……问题就是为什么_rb_free 被调用了…… ps 大概 sprite 没机会挂掉……
@sprite.vss.update
while @dx.update
for j in 0...120
pos = compressLLPos(rand(800),rand(600),@texture.width,@texture.height)
for i in 0...6
@sprite.vss[j*6+i].x = 1#pos[i][0][0]
# @sprite.vss[j*6+i].y = pos[i][0][1]
# @sprite.vss[j*6+i].u = pos[i][1][0]
# @sprite.vss[j*6+i].v = pos[i][1][1]
end
end
@sprite.vss.update
end
@sprite.dispose
@dx.dispose
---------------------------
p
---------------------------
["RgeDx.rb:32:in `compressLLPos'", "RgeDx.rb:60:in `block in <main>'", "RgeDx.rb:59:in `each'", "RgeDx.rb:59:in `<main>'", "RgeCore:in `eval'"]
---------------------------
确定
---------------------------
我什么都看不懂了……看起来是在 compressLLPos 的时候分配内存然后被回收了……这不科学啊!!
mark 在 1.9.3 之前是设置对象头的一个 flag, 在 1.9.3 之后是在一个 bitset 里设置一个位,mark 完的对象就不会 free.
2.1 之前是用 Knüth 的手工栈法避免递归 mark, 2.1 后优化了手工栈。
不过你可以记录下所有 mark 过的 vectorSetting 的地址,然后和析构里的 this 作对比...