[racket] Some problem with hash-update!

From: Evgeny Odegov (oev-racket at sibmail.com)
Date: Mon Sep 15 04:04:12 EDT 2014

> I think that changing `_pointer` to `_DWORD` can't be the real answer,
> since `_pointer` is at least as large as `_DWORD`.

Facepalm. Of course, you're right! Somehow, I've thought that _pointer
 is twice shorter :)

> But I agree that you should use `malloc`, and you should also supply
> 'atomic-interior:
>
>  (malloc _DWORD 'atomic-interior)
>
> The 'atomic-interior flag ensures that the allocated memory does not
> move during an invocation of the callback.
>

It seems like I've got a wrong impression about #:atomic? parameter of
`_fun` form. I thought it's intended to prevent such issues.


> Along similar lines, I think you need to add
>
>  #:malloc-mode 'atomic-interior
>
> to the declaration of `_CMN_ERROR`.
>

Thank you for the notes!  So, as I see, `malloc' with 'atomic-inferior mode
must be used, when a parameter is changed by foreign function.


> You may need to copy the `filter` argument into non-moving memory, but
> that's probably not an issue if it's always "".

The parameter `lpszFilter` is not changed by `TXTEnumInfoText`.
Is `_string/locale` enough in such case?

What could you say about `_string/locale/len'?
Is there something that I have not took into account?


>
> At Mon, 15 Sep 2014 11:07:52 +0700 (NOVT), "Evgeny Odegov" wrote:
>> More complete example:
>> http://pasterack.org/pastes/25901
>>
>> I guess I've found reason of the problem.
>>
>> I think the problem was in that line:
>> (define lpdwItems (make-bytes (ctype-sizeof _pointer) 0))
>>
>> I've changed it to:
>> (define lpdwItems (make-bytes (ctype-sizeof _DWORD) 0))
>>
>> There is no visible problems now, but I doubt that applying `make-bytes'
>> here is right.
>>
>> Should I use `malloc' in such cases?
>>
>>
>> Anyway, sorry for the noise.
>>
>>
>> > My best guess is that it's an issue with memory management, because
>> > memory management gets a lot trickier when you call a function that
>> can
>> > call back into Racket. A GC can happen during the callback, and
>> > therefore during the dynamic extent of the foreign-function call,
>> which
>> > can move arguments that were passed to the foreign function, for
>> example.
>> >
>> > Would it be possible to provide a complete example?
>> >
>> > At Sat, 13 Sep 2014 22:45:28 +0700 (NOVT), "Evgeny Odegov" wrote:
>> >> Oh, I'm wrong. The last code is not equivalent to initial.
>> >> The equivalent code has this problem:
>> >>
>> >> (define result (make-hash))
>> >> (define big-list (list))
>> >> (define (callback dwTextID lpszInfoText lpvUser)
>> >>   (if (equal? lpszInfoText "")
>> >>       (set! big-list (append big-list (list dwTextID)))
>> >>       (hash-update! result
>> >>                     lpszInfoText
>> >>                     (lambda (id-lst)
>> >>                       (define v (list dwTextID))
>> >>                       (append id-lst v))
>> >>                     '()))
>> >>   #t)
>> >>
>> >>
>> >> The code with `cons' instead `append' works fine:
>> >>
>> >> (define result (make-hash))
>> >> (define (callback dwTextID lpszInfoText lpvUser)
>> >>   (hash-update! result
>> >>                 lpszInfoText
>> >>                 (lambda (id-lst)
>> >>                   (define new-id-lst (cons dwTextID id-lst))
>> >>                   (unless (list? new-id-lst)
>> >>
>> >>                     (error "~v" new-id-lst))
>> >>                   new-id-lst)
>> >>                 '())
>> >>   #t)
>> >>
>> >>
>> >>
>> >>
>> >> ____________________
>> >>   Racket Users list:
>> >>   http://lists.racket-lang.org/users
>> >
>



Posted on the users mailing list.