On 2011-01-14, at 4:37 PM, David Bridgham wrote:
On 01/14/2011 02:53 PM, Marc Feeley wrote:
However, while trying this from a different machine this morning I came across a rather strange effect. If I'm running it to a remote X display, it doesn't crash. Only crashes if the bounce program is running on the same machine as my display
Could it be that your Xlib is returning a pointer to a statically allocated Screen structure? It is hard to tell from the Xlib documentation what is guaranteed to be a freshly allocated structure and what can be statically allocated. Do you know?
Turns out it was not because of running it on a remote machine vs local, but whether I was running it from screen 0 or screen 1. One of the two machines I've been using is dual-headed.
An array of screen structures is allocated and stashed away in the display structure. If I run it on Screen 1, the screen pointer points into the middle of the allocated memory block and XFree crashes. If I run it from screen 0, the screen pointer points to the beginning of the allocated memory and XFree "works", though I suspect it leaves a stale pointer in the display structure.
I think it's safe to not free the screen structure explicitly as it will be free'd later when XCloseDisplay is called which calls _XFreeDisplayStructure. At least that's what I see in the Xlib sources I have.
-Dave
That's a great analysis! It means that XScreenOfDisplay does not return a pointer to a fresh Screen. It is a pointer to a shared structure, whose deallocation is the responsibility of Xlib. In other words, Xlib.scm should not say:
(define XScreenOfDisplay (c-lambda (Display* ;; display int) ;; screen_number Screen*/XFree "XScreenOfDisplay"))
it should say:
(define XScreenOfDisplay (c-lambda (Display* ;; display int) ;; screen_number Screen* "XScreenOfDisplay"))
That way the pointer to the Screen returned by XScreenOfDisplay will not be managed by the Gambit garbage collector (when the Scheme world drops the pointer to the Screen, it must not be passed to XFree).
Marc