Issue #98 invalid

Struct members get garbage collected even when the struct still has references

Brodie Rao
staff created an issue

Given code like this:

from cffi import FFI

ffi = FFI()
ffi.cdef("""
    int printf(const char *, ...);

    typedef struct {
         const char *s;
    } thing_t;
""")
C = ffi.dlopen(None)

def makething(s):
    return ffi.new('thing_t *', (ffi.new('char[]', s),)), s

def brokenhello():
    thing = makething('world')[0]
    C.printf('hello "%s"\n', thing.s)

def workinghello():
    thing, s = makething('world')
    C.printf('hello "%s"\n', thing.s)

brokenhello()
workinghello()

I get the following output:

hello ""
hello "world"

I would expect the char * member of the thing_t instance to have a reference to it by the struct instance. I wouldn't expect it to be garbage collected until the reference count for the struct hits zero.

Comments (1)

  1. Armin Rigo

    The docs try to say clearly that this expectation, while reasonable from a ctypes point of view, is wrong with CFFI: see http://cffi.readthedocs.org/, paragraph """when this exact object is garbage-collected""".

    The motivation is that what you want --- the ctypes approach --- involves guesses that might not be correct. For example the char[] array should stay alive, but what if C code then replaces the thing_t.s field with NULL? The original char[] array will continue to stay alive and leak, as in ctypes. And we have no clue if C code copied the pointer somewhere else, or not. So instead of guessing, you need to explicitly keep the Python object returned by ffi.new() alive as long as needed.

  2. Log in to comment