I am facing some kind of issues that I am having difficulties to solve. I am getting the following error during runtime:
Traceback (most recent call last) /home/jose/src/VapourSynth.nim/src/filters/modifyframe.nim(9) modifyframe /home/jose/src/VapourSynth.nim/src/output.nim(115) Savey4m /home/jose/src/VapourSynth.nim/src/output.nim(83) writeY4mFrames /home/jose/src/VapourSynth.nim/src/vsframe.nim(114) getFrame /home/jose/src/VapourSynth.nim/src/filters/DrawFrame.nim(24) DrawFrameGetFrame /home/jose/src/VapourSynth.nim/src/filters/kernel.nim(12) apply_kernel /home/jose/src/VapourSynth.nim/src/vsframe.nim(184) [] /home/jose/src/VapourSynth.nim/src/vsframe.nim(166) getPlane /home/jose/.choosenim/toolchains/nim-1.0.6/lib/system/gc.nim(439) newObj SIGSEGV: Illegal storage access. (Attempt to read from nil?)
The function that is failing is the following:
proc getPlane*(frame:ptr VSFrameRef, plane:Natural):Plane =
if frame == nil:
raise newException(ValueError, "called with nil pointer")
let frameFormat = getFrameFormat(frame)
#echo "FRAME FORMAT------------> ", repr frameFormat
#echo frameFormat.bytesPerSample
#let format = frameFormat.toFormat
if plane > frameFormat.numPlanes-1:
raise newException(ValueError, "the plane requested is above the number of planes available")
let width = getFrameWidth( frame, plane )
let height = getFrameHeight( frame, plane )
let stride = getStride(frame, plane )
let planeptr = getReadPtr(frame, plane) # Plane pointer
let planeptrW = getWritePtr(frame, plane)
let ssW = if plane > 0: frameFormat.subSamplingW else: 0
let ssH = if plane > 0: frameFormat.subSamplingH else: 0
let bytesPerSample = frameFormat.bytesPerSample.int
# TODO: to deal with bigger bytes per sample
var rowPointers:seq[ptr UncheckedArray[uint8]]
newSeq(rowPointers, height)
let ini = cast[int](planeptrW)
#echo "INI: ", ini, " STRIDE: ", stride
for row in 0..<height:
#echo " value: ", ini + row*stride
rowPointers[row] = cast[ptr UncheckedArray[uint8]]( ini + row * stride )
#echo " row: ", row
echo "ok"
echo &"Width: {width} bytesPerSample: {bytesPerSample} "
#echo bytesPerSample
let rowSize = width * bytesPerSample
Plane( width:width,
height:height,
idx:plane,
ptrIniRead:planeptr,
ptrCurRead:planeptr,
ptrIniWrite:planeptrW,
ptrCurWrite:planeptrW,
rowSize: rowSize,
stride:stride,
subSamplingW:ssW,
subSamplingH:ssH,
bytesPerSample: bytesPerSample,
rows:rowPointers )
The function works fine, but after some time it fails when I first use width:
echo &"Width: {width} bytesPerSample: {bytesPerSample} "
surprisingly it doesn't fail when I do:
let width = getFrameWidth( frame, plane )
Just for information, getFrameWidth is defined as:
proc getFrameWidth*(frame:ptr VSFrameRef, plane:int):int =
## Returns the width of a plane of a given frame, in pixels. The width depends on the plane number because of the possible chroma subsampling.
return API.getFrameWidth(frame, plane.cint).int
which calls a C function defined as:
type
VSAPI* {.bycopy.} = object
....
getFrameWidth*: proc (f: ptr VSFrameRef; plane: cint): cint {.cdecl.}
....
(this struct defines the VapourSynth's API; defined by means of c2nim)
Any clue about what I can do?
The function works fine, but after some time it fails
Are you using default refc GC or new --gc:arc?
I assume default refc. In that case I would assume that there is something wrong in your bindings, so when the GC starts for the first time it fails. You may call GC_Fullcollect() early, then the bug may occur earlier.
And you can try too compile with --gc:arc -d:useMalloc, then you have a more deterministic GC and the error may come earlier. In this case you can also try running your app by valgrind, valgrind may tell you details.
You can also play with --gc:none, maybe then your app runs longer, until all memory is consumed.
That are the first steps I would try...
Thanks Stefan.
So:
nim c -r modifyframe
fails after 6 frames as explained before.
arc fails for me:
$ nim c --gc:arc modifyframe Hint: used config file '/home/jose/.choosenim/toolchains/nim-1.0.6/config/nim.cfg' [Conf] command line(1, 2) Error: 'none', 'boehm' or 'refc' expected, but 'arc' found
With valgrind (first time using it) takes me a bit further (14 frames). I pasted the outcome here.
If I activate more flags I get this <https://pastebin.com/Y4AKfrku>.
I don't know what to do with that information :O/.
Ah yes, arc is available in devel. But try --gc:none, maybe also boehm.
Of course that will not really help, the bug is not Nim GC but your bindings, but maybe it gives somehow more insight.
I think valgrind does only help with --gc:arc and -d:useMalloc.
echo &"Width: {width} bytesPerSample: {bytesPerSample} "
I pass from 369 errors in 61 contexts to 0. Why could that be?
I don't think that your problem is in some way related to the echo statement -- echo may in this case only trigger the bug, maybe because due to echo new memory is allocated or freed.
Such types of bugs are very hard.
The echo statement might trigger a call to getFrameWidth().
Try to do an "old style" echo like 'echo "Width: " & $width' directly after a getFrameWidth() call and assigning its result ("let width = getFrameWidth(...)".