var p = cast[ptr fuck](L.newuserdata(sizeof(fuck).cint))
You allocate memory which is not zeroed. So its content may change depending on what it was used for beforehand.
echo repr(p)
Now you want a representation of that memory. p.ud may have any value here. If it is not nil, repr will try to resolve it to give you a representation of its content. What happens is that after those echo s, p.ud contains some garbage and repr tries to interpret that as a pointer and follows it, resulting in a SIGSEGV.
So just move the echo repr(p) line after p.ud = new(test2).
yes, after I read the sourcecode of nimLUA, i find the problem, just need to add zeroMem after newuserdata, actually if I don't use zeroMem and just exec :p.ud = new(test2) after newuserdata, it's also crashed.
import lua
var L = newState()
L.openlibs()
type
test2 = ref object
a :int
b :string
fuck = object
ud:test2
L.newtable()
L.pushstring("new")
L.pushcfunction(proc(l:PState):cint{.cdecl.}=
var p = cast[ptr fuck](L.newuserdata(sizeof(fuck).cint))
#zeroMem(p, sizeof(fuck))
p.ud = new(test2)
echo repr(p)
#GC_ref(p.ud)
return 1)
L.settable(-3)
L.setGlobal("testtype")
var res = L.dofile("a.lua")
if res > 0: echo "testfail:" & L.tostring(-1)
L.close()
Traceback (most recent call last)
a.nim(23) a
lua.nim(593) dofile
a.nim(16) :anonymous
gc.nim(292) unsureAsgnRef
gc.nim(180) decRef
SIGSEGV: Illegal storage access. (Attempt to read from nil?)