Closed v0dro closed 6 years ago
Yeah, it's inferring that the dtype is int64 (based on the 1) when it should probably be object. It's probably trying to deallocate the nil or something funky like that.
@lokeshh
One thing I don't understand is the reason behind the segfault happening after I quit the session. This does not happen in irb. Any particular reason for that?
This is similar to #452. The basic problem seems to be when a Ruby exception gets called within NMatrix C code. As to why it happens it on exit, it must must be something that happens during cleanup, maybe a double free, or a free at an address that got garbled somehow. Just a guess.
Or maybe the fact that nil
is actually an object but it doesn't get registered with the GC by NMatrix just before it throws the error? Something like that?
More likely it's because it's decreasing the ref count on Qnil improperly (as in, it isn't increasing it first). Since it's Qnil, it really shouldn't have its ref count messed with.
Then again, I may be mixing it up with Python. Argh. Differences between writing extensions for two scripting languages is hard to keep track of.
@mohawkjohn I just learned from Koichi while writing Rubex that maintaining ref count is not necessary in Ruby since it uses a conservative mark and sweep algorithm. They have done this on purpose so that writing C extensions in easier. Maybe we should relook the nmatrix architecture and bring it upto speed with the actual Ruby implementation.
@v0dro We count references because of issues with writing Ruby in C++ and exception unwinding.
Oh. So you mean that if it were an entirely C library that would not be needed? Also, what do you mean by exception unwinding? I don't seem to recall C++ exceptions being used anywhere in nmatrix.
If you use rb_raise
, it skips right out of the function and doesn't unwind. As such, destructors are not called for objects that need to be freed.
How about using rb_ensure
for the memory freeing? The rcsv
gem uses this: https://github.com/fiksu/rcsv/blob/master/ext/rcsv/rcsv.c#L524
Maybe enforce some library-wide convention that memory allocations must be made inside such ensure blocks?
Is this still a problem?
This code
NMatrix.new([2],[1,nil])
causes pry to segfault after quitting pry: