[gambit-list] Memory leak (?) using `c-define`d functions from foreign release functions.
Estevo
euccastro at gmail.com
Wed Jan 1 05:08:37 EST 2014
Ah no, not all still objects have a data field; only ___alloc_rc'ed ones.
On Wed, Jan 1, 2014 at 10:51 AM, Estevo <euccastro at gmail.com> wrote:
> But wait a minute... I had missed the point that foreigns themselves (that
> is, not only the data they point to) have a reference count. Sure enough,
> foreigns that are returned by POINTER_to_SCMOBJ *are ___STILL allocated*!
> That means they already have the `data` field I wanted to add to Gambit!
>
> *slaps forehead*
>
>
> On Mon, Dec 30, 2013 at 7:54 PM, Estevo <euccastro at gmail.com> wrote:
>
>> (Ignore the "q is ..." printout. As you see in the script, I just
>> printed p again there instead, by mistake.)
>>
>>
>> On Mon, Dec 30, 2013 at 7:51 PM, Estevo <euccastro at gmail.com> wrote:
>>
>>> Well, just with 2 (modified script follows below, again) I get memory
>>> corruption (note that it seems like the value of the car of `ptr-serials`
>>> has become the string "*** after GC", which is only ever passed to println.)
>>>
>>> p is #<point* #2 0x28979a0>
>>> q is #<point* #2 0x28979a0>
>>>
>>> release-point called on serial 3
>>> found in object table as: #<void* #3 0x28981b0>
>>>
>>> release-point called on serial 4
>>> found in object table as: #<void* #4 0x28979a0>
>>>
>>> *** after GC:
>>> foreign serial is *** after GC:, corresponding to not-there, a
>>> mem-allocated something else object with reference count == 10008704
>>>
>>> Bye.
>>>
>>>
>>> ;----
>>>
>>> (c-declare "struct { int x; int y; } point;")
>>>
>>> (define no-err ((c-lambda () scheme-object "___result =
>>> ___FIX(___NO_ERR);")))
>>>
>>> (define ptr-serials '())
>>>
>>>
>>> (c-define (release-point ptr)
>>> ((pointer void)) scheme-object "scm_release_point" ""
>>> (let ((ptr-serial (object->serial-number ptr)))
>>> (set! ptr-serials (cons ptr-serial ptr-serials))
>>>
>>> (println "release-point called on serial " ptr-serial)
>>> (println "found in object table as: "
>>> (table-ref ##serial-number-to-object-table ptr-serial
>>> 'not-there)))
>>>
>>> ((c-lambda ((pointer void)) void "___release_rc") ptr)
>>> no-err)
>>>
>>> (c-define-type point (type "point" (point*) "scm_release_point"))
>>>
>>> (define p ((c-lambda () point
>>> "___result_voidstar =
>>> ___EXT(___alloc_rc)(sizeof(point));")))
>>>
>>> (define q ((c-lambda () point
>>> "___result_voidstar =
>>> ___EXT(___alloc_rc)(sizeof(point));")))
>>>
>>> (println "p is " p)
>>> (println "q is " p)
>>>
>>> (set! p #f)
>>> (set! q #f)
>>>
>>> (##gc)
>>>
>>> (newline)
>>> (println "*** after GC:")
>>> (for-each
>>> (lambda (ptr-serial)
>>>
>>> (print "foreign serial is " ptr-serial)
>>> (print ", corresponding to "
>>> (table-ref ##serial-number-to-object-table ptr-serial
>>> 'not-there))
>>>
>>> (print ", a "
>>> (if
>>> ((c-lambda (scheme-object) bool "___result =
>>> ___MEM_ALLOCATED(___arg1);")
>>> (table-ref ##serial-number-to-object-table ptr-serial
>>> 'not-there)) "" "not")
>>> " mem-allocated")
>>>
>>> (print " "
>>> ((c-lambda (scheme-object) char-string "___result =
>>> ___HD_TYP(___BODY(___arg1)[-1]) == ___STILL ? \"still\" : \"something
>>> else\";")
>>> (table-ref ##serial-number-to-object-table ptr-serial
>>> 'not-there)))
>>>
>>> (println " object with reference count == "
>>> ((c-lambda (scheme-object) int "___result =
>>> ___UNTAG(___arg1)[___BODY_OFS - 6 + 1];")
>>> (table-ref ##serial-number-to-object-table ptr-serial
>>> 'not-there)))
>>> (newline))
>>> ptr-serials)
>>>
>>> (println "Bye.")
>>>
>>>
>>>
>>>
>>> On Mon, Dec 30, 2013 at 6:56 PM, Mikael <mikael.rcv at gmail.com> wrote:
>>>
>>>> What's the behvior if you allocate 1 000 000 instead, is the problem
>>>> amplified proportionally?
>>>>
>>>>
>>>> 2013/12/30 Estevo <euccastro at gmail.com>
>>>>
>>>>> It seems that's not the problem. Refcount is 0, yet the object is
>>>>> kept alive.
>>>>>
>>>>> Running the modified script below, I get the following:
>>>>>
>>>>> [BEGIN OUTPUT]
>>>>>
>>>>> p is #<point* #2 0x12309a0>
>>>>> release-point called on serial 3
>>>>> found in object table as: #<void* #3 0x12309a0>
>>>>>
>>>>> *** after GC:
>>>>> foreign serial is 3, corresponding to #<void* #3 0x12309a0>, a
>>>>> mem-allocated still object with reference count == 0
>>>>> Bye.
>>>>>
>>>>> [END OUTPUT]
>>>>>
>>>>>
>>>>> ;--------------------------------------------------------------------------------------
>>>>>
>>>>>
>>>>> (c-declare "struct { int x; int y; } point;")
>>>>>
>>>>> (define no-err ((c-lambda () scheme-object "___result =
>>>>> ___FIX(___NO_ERR);")))
>>>>>
>>>>> (define ptr-serial #f)
>>>>>
>>>>>
>>>>> (c-define (release-point ptr)
>>>>> ((pointer void)) scheme-object "scm_release_point" ""
>>>>> (set! ptr-serial (object->serial-number ptr))
>>>>> (println "release-point called on serial " ptr-serial)
>>>>> (println "found in object table as: "
>>>>> (table-ref ##serial-number-to-object-table ptr-serial 'not-there))
>>>>>
>>>>> ((c-lambda ((pointer void)) void "___release_rc") ptr)
>>>>> no-err)
>>>>>
>>>>> (c-define-type point (type "point" (point*) "scm_release_point"))
>>>>>
>>>>>
>>>>> (define p ((c-lambda () point
>>>>> "___result_voidstar =
>>>>> ___EXT(___alloc_rc)(sizeof(point));")))
>>>>>
>>>>> (println "p is " p)
>>>>>
>>>>> (set! p #f)
>>>>>
>>>>> (##gc)
>>>>>
>>>>> (newline)
>>>>> (println "*** after GC:")
>>>>> (print "foreign serial is " ptr-serial)
>>>>> (print ", corresponding to "
>>>>> (table-ref ##serial-number-to-object-table ptr-serial 'not-there))
>>>>>
>>>>> (print ", a "
>>>>> (if ((c-lambda (scheme-object) bool "___result =
>>>>> ___MEM_ALLOCATED(___arg1);")
>>>>> (table-ref ##serial-number-to-object-table ptr-serial
>>>>> 'not-there))
>>>>> ""
>>>>> "not")
>>>>> " mem-allocated")
>>>>>
>>>>> (print " "
>>>>> ((c-lambda (scheme-object) char-string "___result =
>>>>> ___HD_TYP(___BODY(___arg1)[-1]) == ___STILL ? \"still\" : \"something
>>>>> else\";")
>>>>> (table-ref ##serial-number-to-object-table ptr-serial 'not-there)))
>>>>>
>>>>> (println " object with reference count == "
>>>>> ((c-lambda (scheme-object) int "___result =
>>>>> ___UNTAG(___arg1)[___BODY_OFS - 6 + 1];")
>>>>> (table-ref ##serial-number-to-object-table ptr-serial
>>>>> 'not-there)))
>>>>>
>>>>> (println "Bye.")
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On Mon, Dec 30, 2013 at 10:09 AM, Mikael <mikael.rcv at gmail.com> wrote:
>>>>>
>>>>>> Refcount is 1 by default so you need to decrease it for it to GFC?
>>>>>>
>>>>>> Allocate a zillion points and check the two respective ways.
>>>>>>
>>>>>>
>>>>>> 2013/12/29 Estevo <euccastro at gmail.com>
>>>>>>
>>>>>>> Here's a more realistic version of what I was trying to do:
>>>>>>>
>>>>>>> (c-declare "struct { int x; int y; } point;")
>>>>>>>
>>>>>>> (define no-err ((c-lambda () scheme-object "___result =
>>>>>>> ___FIX(___NO_ERR);")))
>>>>>>>
>>>>>>> (c-define (release-point ptr)
>>>>>>> ((pointer void)) scheme-object "scm_release_point" ""
>>>>>>> (println "release-point called")
>>>>>>> ((c-lambda ((pointer void)) void "___release_rc") ptr)
>>>>>>> no-err)
>>>>>>>
>>>>>>> (c-define-type point (pointer "point" (point*) "scm_release_point"))
>>>>>>>
>>>>>>>
>>>>>>> (define p ((c-lambda () point
>>>>>>> "___result_voidstar =
>>>>>>> ___EXT(___alloc_rc)(sizeof(point));")))
>>>>>>>
>>>>>>> (println "p is " p)
>>>>>>> (set! p #f)
>>>>>>>
>>>>>>> (##gc)
>>>>>>>
>>>>>>> (println "Bye.")
>>>>>>>
>>>>>>> valgrind's complaint is different in this one. What is leaked here
>>>>>>> (again, unless valgrind is giving me a false positive) seems to be the
>>>>>>> Scheme representation of `ptr`:
>>>>>>>
>>>>>>> ==9631== Memcheck, a memory error detector
>>>>>>> ==9631== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et
>>>>>>> al.
>>>>>>> ==9631== Using Valgrind-3.7.0 and LibVEX; rerun with -h for
>>>>>>> copyright info
>>>>>>> ==9631== Command: ./test-c-define
>>>>>>> ==9631==
>>>>>>> p is #<point* #2 0x5c04620>
>>>>>>> release-point called
>>>>>>> Bye.
>>>>>>> ==9631==
>>>>>>> ==9631== HEAP SUMMARY:
>>>>>>> ==9631== in use at exit: 158 bytes in 2 blocks
>>>>>>> ==9631== total heap usage: 154 allocs, 152 frees, 4,247,245 bytes
>>>>>>> allocated
>>>>>>> ==9631==
>>>>>>> ==9631== 158 (87 direct, 71 indirect) bytes in 1 blocks are
>>>>>>> definitely lost in loss record 2 of 2
>>>>>>> ==9631== at 0x4C2B6CD: malloc (in
>>>>>>> /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
>>>>>>> ==9631== by 0x4C7DC6: ___alloc_mem (os_base.c:185)
>>>>>>> ==9631== by 0x4B6905: alloc_mem_aligned (mem.c:452)
>>>>>>> ==9631== by 0x4B77A7: alloc_scmobj_still (mem.c:1245)
>>>>>>> ==9631== by 0x4B78B1: ___alloc_scmobj (mem.c:1285)
>>>>>>> ==9631== by 0x4C3DEE: ___POINTER_to_SCMOBJ (c_intf.c:5154)
>>>>>>> ==9631== by 0x4B1C88: scm_release_point (test-c-define.c:665)
>>>>>>> ==9631== by 0x4C1027: ___release_foreign (c_intf.c:1713)
>>>>>>> ==9631== by 0x4BAEA4: free_unmarked_still_objs (mem.c:3271)
>>>>>>> ==9631== by 0x4BD472: ___garbage_collect (mem.c:4698)
>>>>>>> ==9631== by 0x4E4357: ___H__20___kernel (_kernel.c:9170)
>>>>>>> ==9631== by 0x4B49B2: trampoline (setup.c:1618)
>>>>>>> ==9631==
>>>>>>> ==9631== LEAK SUMMARY:
>>>>>>> ==9631== definitely lost: 87 bytes in 1 blocks
>>>>>>> ==9631== indirectly lost: 71 bytes in 1 blocks
>>>>>>> ==9631== possibly lost: 0 bytes in 0 blocks
>>>>>>> ==9631== still reachable: 0 bytes in 0 blocks
>>>>>>> ==9631== suppressed: 0 bytes in 0 blocks
>>>>>>> ==9631==
>>>>>>> ==9631== For counts of detected and suppressed errors, rerun with: -v
>>>>>>> ==9631== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from
>>>>>>> 2)
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On Thu, Dec 26, 2013 at 11:23 PM, Estevo <euccastro at gmail.com>wrote:
>>>>>>>
>>>>>>>> Valgrind reports Gambit is leaking a "sfun stack marker" if I call,
>>>>>>>> from a foreign release function, another function defined with `c-define`.
>>>>>>>> The code below is about the most innocent looking thing I could come up
>>>>>>>> with.
>>>>>>>>
>>>>>>>> Doesn't Gambit like c-define functions called within release
>>>>>>>> functions, or is Valgrind giving me a false positive here (as it is wont to
>>>>>>>> do quite often.)
>>>>>>>>
>>>>>>>> ; ~/gambit-dbg/bin/gsc -exe -cc-options -g test-c-define.scm &&
>>>>>>>> valgrind --leak-check=full ./test-c-define
>>>>>>>>
>>>>>>>> (c-declare #<<c-declare-end
>>>>>>>>
>>>>>>>> typedef struct { int x; int y; } point;
>>>>>>>>
>>>>>>>> void scm_release_point(unsigned long);
>>>>>>>>
>>>>>>>> ___SCMOBJ c_release_point(void *ptr) {
>>>>>>>> scm_release_point((unsigned long)ptr);
>>>>>>>> ___EXT(___release_rc)(ptr);
>>>>>>>> return ___FIX(___NO_ERR);
>>>>>>>> }
>>>>>>>>
>>>>>>>> c-declare-end
>>>>>>>> )
>>>>>>>>
>>>>>>>> (c-define (release-point ptr) (unsigned-long) void
>>>>>>>> "scm_release_point" ""
>>>>>>>> (println "release-point called"))
>>>>>>>>
>>>>>>>> (c-define-type point (pointer "point" (point*) "c_release_point"))
>>>>>>>>
>>>>>>>> (define p ((c-lambda () point
>>>>>>>> "___result_voidstar =
>>>>>>>> ___EXT(___alloc_rc)(sizeof(point));")))
>>>>>>>>
>>>>>>>> (println "p is " p)
>>>>>>>> (set! p #f)
>>>>>>>>
>>>>>>>> (##gc)
>>>>>>>> ; for good measure...
>>>>>>>> (##gc)
>>>>>>>> (##gc)
>>>>>>>>
>>>>>>>> (println "Bye.")
>>>>>>>>
>>>>>>>>
>>>>>>>> valgrind --leak-check=full ./test-c-define
>>>>>>>> ==16301== Memcheck, a memory error detector
>>>>>>>> ==16301== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward
>>>>>>>> et al.
>>>>>>>> ==16301== Using Valgrind-3.7.0 and LibVEX; rerun with -h for
>>>>>>>> copyright info
>>>>>>>> ==16301== Command: ./test-c-define
>>>>>>>> ==16301==
>>>>>>>> p is #<point* #2 0x5c04640>
>>>>>>>> release-point called
>>>>>>>> Bye.
>>>>>>>> ==16301==
>>>>>>>> ==16301== HEAP SUMMARY:
>>>>>>>> ==16301== in use at exit: 71 bytes in 1 blocks
>>>>>>>> ==16301== total heap usage: 153 allocs, 152 frees, 4,247,198
>>>>>>>> bytes allocated
>>>>>>>> ==16301==
>>>>>>>> ==16301== 71 bytes in 1 blocks are definitely lost in loss record 1
>>>>>>>> of 1
>>>>>>>> ==16301== at 0x4C2B6CD: malloc (in
>>>>>>>> /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
>>>>>>>> ==16301== by 0x4C922E: ___alloc_mem (os_base.c:185)
>>>>>>>> ==16301== by 0x4B7DB5: alloc_mem_aligned (mem.c:452)
>>>>>>>> ==16301== by 0x4B8C57: alloc_scmobj_still (mem.c:1245)
>>>>>>>> ==16301== by 0x4B8D61: ___alloc_scmobj (mem.c:1285)
>>>>>>>> ==16301== by 0x4B8E44: ___make_vector (mem.c:1362)
>>>>>>>> ==16301== by 0x4C677B: ___make_sfun_stack_marker (c_intf.c:6452)
>>>>>>>> ==16301== by 0x4B359E: scm_release_point (test-c-define.c:139)
>>>>>>>> ==16301== by 0x4B354B: c_release_point (test-c-define.c:130)
>>>>>>>> ==16301== by 0x4C24D7: ___release_foreign (c_intf.c:1713)
>>>>>>>> ==16301== by 0x4BC354: free_unmarked_still_objs (mem.c:3271)
>>>>>>>> ==16301== by 0x4BE922: ___garbage_collect (mem.c:4698)
>>>>>>>> ==16301==
>>>>>>>> ==16301== LEAK SUMMARY:
>>>>>>>> ==16301== definitely lost: 71 bytes in 1 blocks
>>>>>>>> ==16301== indirectly lost: 0 bytes in 0 blocks
>>>>>>>> ==16301== possibly lost: 0 bytes in 0 blocks
>>>>>>>> ==16301== still reachable: 0 bytes in 0 blocks
>>>>>>>> ==16301== suppressed: 0 bytes in 0 blocks
>>>>>>>> ==16301==
>>>>>>>> ==16301== For counts of detected and suppressed errors, rerun with:
>>>>>>>> -v
>>>>>>>> ==16301== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2
>>>>>>>> from 2)
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> Gambit-list mailing list
>>>>>>> Gambit-list at iro.umontreal.ca
>>>>>>> https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.iro.umontreal.ca/pipermail/gambit-list/attachments/20140101/c5365948/attachment.htm>
More information about the Gambit-list
mailing list